diff --git a/AUTHORS b/AUTHORS index 9c8a7c7..2270350 100644 --- a/AUTHORS +++ b/AUTHORS
@@ -254,6 +254,7 @@ Kamil Jiwa <kamil.jiwa@gmail.com> Kangil Han <kangil.han@samsung.com> Kangyuan Shu <kangyuan.shu@intel.com> +Kartikey Bhatt <kartikey@amazon.com> Kaspar Brand <googlecontrib@velox.ch> Kaustubh Atrawalkar <kaustubh.ra@gmail.com> Kaustubh Atrawalkar <kaustubh.a@samsung.com>
diff --git a/DEPS b/DEPS index 0287be5..729b096 100644 --- a/DEPS +++ b/DEPS
@@ -34,27 +34,27 @@ 'llvm_url': 'http://src.chromium.org/llvm-project', 'llvm_git': 'https://llvm.googlesource.com', 'webkit_trunk': 'http://src.chromium.org/blink/trunk', - 'webkit_revision': 'd522711b3c967e892ae9c969c5e654506cb101bb', # from svn revision 188824 + 'webkit_revision': '12a5230da1aa55ecf6d0696bf73bdbb327ad0aa1', # from svn revision 189000 'chromium_git': 'https://chromium.googlesource.com', 'chromiumos_git': 'https://chromium.googlesource.com/chromiumos', 'pdfium_git': 'https://pdfium.googlesource.com', 'skia_git': 'https://skia.googlesource.com', 'boringssl_git': 'https://boringssl.googlesource.com', - 'libvpx_revision': '8dc6ea93de62df4fb4d8bcc6156c3ad4df158bb3', + 'libvpx_revision': '5da40ca3395cd09443f3d4a3f8b86e495a6df364', 'sfntly_revision': '1bdaae8fc788a5ac8936d68bf24f37d977a13dac', - 'skia_revision': '2dca817edb0d741b7d8930009417bf9bd071808d', + 'skia_revision': 'f7069d58fc7b323437e8a65a82d5d839e92c9ffe', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and V8 without interference from each other. 'v8_branch': 'trunk', - 'v8_revision': '3efdae6669030b03a841c8d579655ba1f36b1f87', + 'v8_revision': '803048b5d6457cfb87a66470e14fc49919497bea', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling WebRTC # and V8 without interference from each other. # 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. - 'swarming_revision': 'e98dde9a7c9a349125179448c957606987f845a3', + 'swarming_revision': 'd863df38343f8057dbddfe5543addcf19a49ce0f', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. @@ -74,7 +74,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling BoringSSL # and whatever else without interference from each other. - 'boringssl_revision': '5fa3eba03d1912424decc885e72da20a6a08d8e7', + 'boringssl_revision': '347f025d752980f62757f3f01321c4ec970ba94c', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling nss # and whatever else without interference from each other. @@ -107,7 +107,7 @@ deps = { 'src/breakpad/src': - Var('chromium_git') + '/external/google-breakpad/src.git' + '@' + '58aca2ddf2f7d873b8705886c8cce1b3f68c2bc9', # from svn revision 1413 + Var('chromium_git') + '/external/google-breakpad/src.git' + '@' + '398c70a3e6825e2bc77fb4779107b018c58f0612', # from svn revision 1414 'src/buildtools': Var('chromium_git') + '/chromium/buildtools.git' + '@' + Var('buildtools_revision'), @@ -161,7 +161,7 @@ Var('chromium_git') + '/external/grit-i18n.git' + '@' + 'a5890a8118c0c80cc0560e6d8d5cf65e5d725509', # from svn revision 185 'src/tools/gyp': - Var('chromium_git') + '/external/gyp.git' + '@' + 'adb7d24b9fc166f01ab2da50478556b518a9218f', # from svn revision 2027 + Var('chromium_git') + '/external/gyp.git' + '@' + 'b28bd7ddd1438c98f93a8e5383b7daceb572a3fb', # from svn revision 2028 'src/tools/swarming_client': Var('chromium_git') + '/external/swarming.client.git' + '@' + Var('swarming_revision'), @@ -197,7 +197,7 @@ Var('chromium_git') + '/external/bidichecker/lib.git' + '@' + '97f2aa645b74c28c57eca56992235c79850fa9e0', 'src/third_party/webgl/src': - Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'ff796782c581a03c5f36e547b8218a23083c8534', + Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '0c2bcf36a740181f50ce94a0eaad357219441dee', 'src/third_party/swig/Lib': Var('chromium_git') + '/chromium/deps/swig/Lib.git' + '@' + 'f2a695d52e61e6a8d967731434f165ed400f0d69', @@ -209,10 +209,10 @@ Var('chromium_git') + '/chromium/deps/libvpx.git' + '@' + Var('libvpx_revision'), 'src/third_party/ffmpeg': - Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + 'ff47c53afa6bc5a2d705c569dbca324d71447f6f', + Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + '43b80ebd6a901d6828c73060dd1494daf795779d', 'src/third_party/libjingle/source/talk': - Var('chromium_git') + '/external/webrtc/trunk/talk.git' + '@' + 'bf56cdc4f274c76ba3afc6b9c7dad591704cb112', # from svn revision 8128 + Var('chromium_git') + '/external/webrtc/trunk/talk.git' + '@' + '419aa31fb0755376324a150605bea2771c7a5a77', # from svn revision 8141 'src/third_party/usrsctp/usrsctplib': Var('chromium_git') + '/external/usrsctplib.git' + '@' + '190c8cbfcf8fd810aa09e0fab4ca62a8ce724e14', @@ -236,7 +236,7 @@ Var('chromium_git') + '/native_client/src/third_party/scons-2.0.1.git' + '@' + '1c1550e17fc26355d08627fbdec13d8291227067', 'src/third_party/webrtc': - Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + '5bcc39334adc79f1d8d2d94b596bb558b2a402b3', # from svn revision 8130 + Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + '67d96fc219699fe48ca9dd62153f55641b3e03cb', # from svn revision 8141 'src/third_party/openmax_dl': Var('chromium_git') + '/external/webrtc/deps/third_party/openmax.git' + '@' + Var('openmax_dl_revision'), @@ -268,7 +268,7 @@ Var('chromium_git') + '/chromium/tools/deps2git.git' + '@' + 'f04828eb0b5acd3e7ad983c024870f17f17b06d9', 'src/third_party/webpagereplay': - Var('chromium_git') + '/external/web-page-replay.git' + '@' + '818d4271650f4f83d1635e94549e8457584dfac4', + Var('chromium_git') + '/external/web-page-replay.git' + '@' + '2f7b704b8b567983c040f555d3e46f9766db8e87', 'src/third_party/pywebsocket/src': Var('chromium_git') + '/external/pywebsocket/src.git' + '@' + 'cb349e87ddb30ff8d1fa1a89be39cec901f4a29c',
diff --git a/PRESUBMIT.py b/PRESUBMIT.py index ad5b854..33008be 100644 --- a/PRESUBMIT.py +++ b/PRESUBMIT.py
@@ -174,6 +174,7 @@ r"simple_platform_shared_buffer_posix\.cc$", r"^net[\\\/]disk_cache[\\\/]cache_util\.cc$", r"^net[\\\/]url_request[\\\/]test_url_fetcher_factory\.cc$", + r"^ui[\\\/]ozone[\\\/]platform[\\\/]dri[\\\/]native_display_delegate_proxy\.cc$", ), ), ( @@ -1218,7 +1219,7 @@ return checkstyle.RunCheckstyle( input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml', - black_list=_EXCLUDED_PATHS) + black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST) def _CheckForCopyrightedCode(input_api, output_api):
diff --git a/WATCHLISTS b/WATCHLISTS index 7586eb9..e20e539 100644 --- a/WATCHLISTS +++ b/WATCHLISTS
@@ -952,13 +952,12 @@ 'dcheng@chromium.org', 'jianli@chromium.org'], 'password_manager': ['mkwst+watchlist-passwords@chromium.org', 'gcasto+watchlist@chromium.org'], - 'pepper_api': ['piman+watch@chromium.org', 'ihf+watch@chromium.org', + 'pepper_api': ['bradnelson+warch@chromium.org', + 'piman+watch@chromium.org', 'ihf+watch@chromium.org', 'yusukes+watch@chromium.org', 'raymes+watch@chromium.org', - 'noelallen@chromium.org', 'binji+watch@chromium.org', - 'nfullagar@chromium.org', 'teravest+watch@chromium.org', + 'binji+watch@chromium.org', 'teravest+watch@chromium.org', 'tzik@chromium.org'], - 'plugin': ['jam@chromium.org', - 'stuartmorgan+watch@chromium.org'], + 'plugin': ['jam@chromium.org'], 'predictors': ['shishir+watch@chromium.org'], 'prepopulated_engines': ['vasilii+watch@chromium.org'], 'prerender': ['cbentzel+watch@chromium.org', 'tburkard+watch@chromium.org',
diff --git a/android_webview/android_webview.gyp b/android_webview/android_webview.gyp index 6d0430c..4018c9f2c 100644 --- a/android_webview/android_webview.gyp +++ b/android_webview/android_webview.gyp
@@ -120,6 +120,7 @@ '../third_party/WebKit/public/blink.gyp:blink', '../ui/gl/gl.gyp:gl', '../ui/shell_dialogs/shell_dialogs.gyp:shell_dialogs', + '../v8/tools/gyp/v8.gyp:v8', '../webkit/common/gpu/webkit_gpu.gyp:webkit_gpu', 'android_webview_pak', 'android_webview_version', @@ -156,6 +157,9 @@ 'browser/aw_javascript_dialog_manager.h', 'browser/aw_login_delegate.cc', 'browser/aw_login_delegate.h', + 'browser/aw_message_port_message_filter.cc', + 'browser/aw_message_port_message_filter.h', + 'browser/aw_message_port_service.h', 'browser/aw_pref_store.cc', 'browser/aw_pref_store.h', 'browser/aw_printing_message_filter.cc', @@ -226,6 +230,7 @@ 'common/aw_crash_handler.h', 'common/aw_hit_test_data.cc', 'common/aw_hit_test_data.h', + 'common/aw_message_port_messages.h', 'common/aw_resource.h', 'common/aw_switches.cc', 'common/aw_switches.h', @@ -245,6 +250,8 @@ 'renderer/aw_content_renderer_client.h', 'renderer/aw_key_systems.cc', 'renderer/aw_key_systems.h', + 'renderer/aw_message_port_client.cc', + 'renderer/aw_message_port_client.h', 'renderer/aw_permission_client.cc', 'renderer/aw_permission_client.h', 'renderer/aw_render_process_observer.cc',
diff --git a/android_webview/browser/aw_browser_context.cc b/android_webview/browser/aw_browser_context.cc index 1fea722..16d47245 100644 --- a/android_webview/browser/aw_browser_context.cc +++ b/android_webview/browser/aw_browser_context.cc
@@ -18,11 +18,9 @@ #include "base/prefs/pref_service.h" #include "base/prefs/pref_service_factory.h" #include "components/autofill/core/common/autofill_pref_names.h" -#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.h" +#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_prefs.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h" -#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_statistics_prefs.h" -#include "components/data_reduction_proxy/core/common/data_reduction_proxy_event_store.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h" #include "components/user_prefs/user_prefs.h" #include "components/visitedlink/browser/visitedlink_master.h" @@ -36,9 +34,11 @@ using base::FilePath; using content::BrowserThread; -using data_reduction_proxy::DataReductionProxyConfigurator; -using data_reduction_proxy::DataReductionProxyEventStore; -using data_reduction_proxy::DataReductionProxySettings; + +namespace data_reduction_proxy { +class DataReductionProxyConfigurator; +class DataReductionProxyStatisticsPrefs; +} namespace android_webview { @@ -117,14 +117,16 @@ // Can't enable Data reduction proxy if user pref service is not ready. if (context == NULL || context->user_pref_service_.get() == NULL) return; - DataReductionProxySettings* proxy_settings = + data_reduction_proxy::DataReductionProxySettings* proxy_settings = context->GetDataReductionProxySettings(); if (proxy_settings == NULL) return; - + // At this point, context->PreMainMessageLoopRun() has run, so + // context->data_reduction_proxy_io_data() is valid. + DCHECK(context->GetDataReductionProxyIOData()); context->CreateDataReductionProxyStatisticsIfNecessary(); proxy_settings->SetDataReductionProxyStatisticsPrefs( - context->data_reduction_proxy_statistics_.get()); + context->GetDataReductionProxyIOData()->statistics_prefs()); proxy_settings->SetDataReductionProxyEnabled(data_reduction_proxy_enabled_); } @@ -157,19 +159,21 @@ make_scoped_ptr(CreateProxyConfigService()).Pass()); data_reduction_proxy_settings_.reset( - new DataReductionProxySettings( + new data_reduction_proxy::DataReductionProxySettings( new data_reduction_proxy::DataReductionProxyParams( data_reduction_proxy::DataReductionProxyParams::kAllowed))); - data_reduction_proxy_event_store_.reset( - new DataReductionProxyEventStore( - BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI))); - data_reduction_proxy_configurator_.reset( - new data_reduction_proxy::DataReductionProxyConfigurator( - BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO), + data_reduction_proxy_io_data_.reset( + new data_reduction_proxy::DataReductionProxyIOData( + data_reduction_proxy::Client::WEBVIEW_ANDROID, + scoped_ptr< + data_reduction_proxy::DataReductionProxyStatisticsPrefs>(), + data_reduction_proxy_settings_.get(), url_request_context_getter_->GetNetLog(), - data_reduction_proxy_event_store_.get())); + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO), + BrowserThread::GetMessageLoopProxyForThread( + BrowserThread::UI))); data_reduction_proxy_settings_->SetProxyConfigurator( - data_reduction_proxy_configurator_.get()); + data_reduction_proxy_io_data_->configurator()); visitedlink_master_.reset( new visitedlink::VisitedLinkMaster(this, this, false)); @@ -219,24 +223,33 @@ return form_database_service_.get(); } -DataReductionProxySettings* AwBrowserContext::GetDataReductionProxySettings() { +data_reduction_proxy::DataReductionProxySettings* +AwBrowserContext::GetDataReductionProxySettings() { return data_reduction_proxy_settings_.get(); } -DataReductionProxyEventStore* - AwBrowserContext::GetDataReductionProxyEventStore() { - return data_reduction_proxy_event_store_.get(); +data_reduction_proxy::DataReductionProxyIOData* +AwBrowserContext::GetDataReductionProxyIOData() { + return data_reduction_proxy_io_data_.get(); } data_reduction_proxy::DataReductionProxyConfigurator* AwBrowserContext::GetDataReductionProxyConfigurator() { - return data_reduction_proxy_configurator_.get(); + return data_reduction_proxy_io_data_->configurator(); } AwURLRequestContextGetter* AwBrowserContext::GetAwURLRequestContext() { return url_request_context_getter_.get(); } +AwMessagePortService* AwBrowserContext::GetMessagePortService() { + if (!message_port_service_.get()) { + message_port_service_.reset( + native_factory_->CreateAwMessagePortService()); + } + return message_port_service_.get(); +} + // Create user pref service for autofill functionality. void AwBrowserContext::CreateUserPrefServiceIfNecessary() { if (user_pref_service_) @@ -261,12 +274,12 @@ user_prefs::UserPrefs::Set(this, user_pref_service_.get()); - if (data_reduction_proxy_settings_.get()) { + if (data_reduction_proxy_settings_) { data_reduction_proxy_settings_->InitDataReductionProxySettings( user_pref_service_.get(), GetRequestContext(), GetAwURLRequestContext()->GetNetLog(), - GetDataReductionProxyEventStore()); + data_reduction_proxy_io_data_->event_store()); data_reduction_proxy_settings_->MaybeActivateDataReductionProxy(true); SetDataReductionProxyEnabled(data_reduction_proxy_enabled_); @@ -360,17 +373,13 @@ void AwBrowserContext::CreateDataReductionProxyStatisticsIfNecessary() { DCHECK(user_pref_service_.get()); - - if (!data_reduction_proxy_statistics_.get()) { - // We don't care about commit_delay for now. It is just a dummy value. - base::TimeDelta commit_delay = base::TimeDelta::FromMinutes(60); - data_reduction_proxy_statistics_ = - scoped_ptr<data_reduction_proxy::DataReductionProxyStatisticsPrefs>( - new data_reduction_proxy::DataReductionProxyStatisticsPrefs( - user_pref_service_.get(), - base::MessageLoopProxy::current(), - commit_delay)); - } + DCHECK(GetDataReductionProxyIOData()); + if (GetDataReductionProxyIOData()->statistics_prefs()) + return; + // We don't care about commit_delay for now. It is just a dummy value. + base::TimeDelta commit_delay = base::TimeDelta::FromMinutes(60); + GetDataReductionProxyIOData()->EnableCompressionStatisticsLogging( + user_pref_service_.get(), commit_delay); } } // namespace android_webview
diff --git a/android_webview/browser/aw_browser_context.h b/android_webview/browser/aw_browser_context.h index a821acf7..b9e1d66a 100644 --- a/android_webview/browser/aw_browser_context.h +++ b/android_webview/browser/aw_browser_context.h
@@ -8,6 +8,7 @@ #include <vector> #include "android_webview/browser/aw_download_manager_delegate.h" +#include "android_webview/browser/aw_message_port_service.h" #include "android_webview/browser/aw_ssl_host_state_delegate.h" #include "base/basictypes.h" #include "base/compiler_specific.h" @@ -30,9 +31,8 @@ namespace data_reduction_proxy { class DataReductionProxyConfigurator; -class DataReductionProxyEventStore; +class DataReductionProxyIOData; class DataReductionProxySettings; -class DataReductionProxyStatisticsPrefs; } namespace net { @@ -91,8 +91,8 @@ data_reduction_proxy::DataReductionProxySettings* GetDataReductionProxySettings(); - data_reduction_proxy::DataReductionProxyEventStore* - GetDataReductionProxyEventStore(); + data_reduction_proxy::DataReductionProxyIOData* + GetDataReductionProxyIOData(); data_reduction_proxy::DataReductionProxyConfigurator* GetDataReductionProxyConfigurator(); @@ -101,6 +101,8 @@ void CreateUserPrefServiceIfNecessary(); + AwMessagePortService* GetMessagePortService(); + // content::BrowserContext implementation. scoped_ptr<content::ZoomLevelDelegate> CreateZoomLevelDelegate( const base::FilePath& partition_path) override; @@ -143,6 +145,7 @@ scoped_refptr<AwURLRequestContextGetter> url_request_context_getter_; scoped_refptr<AwQuotaManagerBridge> quota_manager_bridge_; scoped_ptr<AwFormDatabaseService> form_database_service_; + scoped_ptr<AwMessagePortService> message_port_service_; AwDownloadManagerDelegate download_manager_delegate_; @@ -151,15 +154,11 @@ scoped_ptr<PrefService> user_pref_service_; - scoped_ptr<data_reduction_proxy::DataReductionProxyConfigurator> - data_reduction_proxy_configurator_; - scoped_ptr<data_reduction_proxy::DataReductionProxyStatisticsPrefs> - data_reduction_proxy_statistics_; scoped_ptr<data_reduction_proxy::DataReductionProxySettings> data_reduction_proxy_settings_; - scoped_ptr<data_reduction_proxy::DataReductionProxyEventStore> - data_reduction_proxy_event_store_; scoped_ptr<AwSSLHostStateDelegate> ssl_host_state_delegate_; + scoped_ptr<data_reduction_proxy::DataReductionProxyIOData> + data_reduction_proxy_io_data_; DISALLOW_COPY_AND_ASSIGN(AwBrowserContext); };
diff --git a/android_webview/browser/aw_message_port_message_filter.cc b/android_webview/browser/aw_message_port_message_filter.cc new file mode 100644 index 0000000..74b1aa5f --- /dev/null +++ b/android_webview/browser/aw_message_port_message_filter.cc
@@ -0,0 +1,60 @@ +// Copyright 2015 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 "android_webview/browser/aw_message_port_message_filter.h" + +#include "android_webview/browser/aw_browser_context.h" +#include "android_webview/common/aw_message_port_messages.h" +#include "content/public/browser/message_port_provider.h" + +using content::BrowserThread; +using content::MessagePortProvider; + +namespace android_webview { + +AwMessagePortMessageFilter::AwMessagePortMessageFilter(int route_id) + : BrowserMessageFilter(AwMessagePortMsgStart), route_id_(route_id) { +} + +AwMessagePortMessageFilter::~AwMessagePortMessageFilter() { +} + +void AwMessagePortMessageFilter::OnChannelClosing() { + MessagePortProvider::OnMessagePortDelegateClosing(this); + AwBrowserContext::GetDefault()->GetMessagePortService()-> + OnMessagePortMessageFilterClosing(this); +} + +bool AwMessagePortMessageFilter::OnMessageReceived( + const IPC::Message& message) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(AwMessagePortMessageFilter, message) + IPC_MESSAGE_FORWARD(AwMessagePortHostMsg_ConvertedMessage, + AwBrowserContext::GetDefault()->GetMessagePortService(), + AwMessagePortService::OnConvertedMessage) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; +} + +void AwMessagePortMessageFilter::OnDestruct() const { + BrowserThread::DeleteOnIOThread::Destruct(this); +} + +void AwMessagePortMessageFilter::SendMessage( + int msg_port_route_id, + const base::string16& message, + const std::vector<int>& sent_message_port_ids) { + Send(new AwMessagePortMsg_Message(route_id_, + msg_port_route_id, // same as the port id + message, + sent_message_port_ids)); +} + +void AwMessagePortMessageFilter::SendMessagesAreQueued(int route_id) { + // TODO(sgurun) implement + NOTREACHED(); +} + +} // namespace android_webview
diff --git a/android_webview/browser/aw_message_port_message_filter.h b/android_webview/browser/aw_message_port_message_filter.h new file mode 100644 index 0000000..d63774b --- /dev/null +++ b/android_webview/browser/aw_message_port_message_filter.h
@@ -0,0 +1,45 @@ +// Copyright 2015 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 ANDROID_WEBVIEW_BROWSER_MESSAGE_PORT_MESSAGE_FILTER_H_ +#define ANDROID_WEBVIEW_BROWSER_MESSAGE_PORT_MESSAGE_FILTER_H_ + +#include "base/callback.h" +#include "content/public/browser/browser_message_filter.h" +#include "content/public/browser/message_port_delegate.h" + +namespace android_webview { + +// Filter for Aw specific MessagePort related IPC messages (creating and +// destroying a MessagePort, sending a message via a MessagePort etc). +class AwMessagePortMessageFilter : public content::BrowserMessageFilter, + public content::MessagePortDelegate { + public: + explicit AwMessagePortMessageFilter(int route_id); + + // BrowserMessageFilter implementation. + void OnChannelClosing() override; + bool OnMessageReceived(const IPC::Message& message) override; + void OnDestruct() const override; + + // MessagePortDelegate implementation. + void SendMessage(int msg_port_route_id, + const base::string16& message, + const std::vector<int>& sent_message_port_ids) override; + void SendMessagesAreQueued(int route_id) override; + + private: + friend class content::BrowserThread; + friend class base::DeleteHelper<AwMessagePortMessageFilter>; + + ~AwMessagePortMessageFilter() override; + + int route_id_; + + DISALLOW_COPY_AND_ASSIGN(AwMessagePortMessageFilter); +}; + +} // namespace android_webview + +#endif // ANDROID_WEBVIEW_BROWSER_MESSAGE_PORT_MESSAGE_FILTER_H_
diff --git a/android_webview/browser/aw_message_port_service.h b/android_webview/browser/aw_message_port_service.h new file mode 100644 index 0000000..086480e --- /dev/null +++ b/android_webview/browser/aw_message_port_service.h
@@ -0,0 +1,32 @@ +// Copyright 2015 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 ANDROID_WEBVIEW_BROWSER_AW_MESSAGE_PORT_SERVICE_H_ +#define ANDROID_WEBVIEW_BROWSER_AW_MESSAGE_PORT_SERVICE_H_ + +#include <vector> + +#include "base/values.h" + +namespace android_webview { + +class AwMessagePortMessageFilter; + +// The interface for AwMessagePortService +class AwMessagePortService { + public: + virtual ~AwMessagePortService() { } + + virtual void OnConvertedMessage( + int message_port_id, + const base::ListValue& message, + const std::vector<int>& sent_message_port_ids) = 0; + + virtual void OnMessagePortMessageFilterClosing( + AwMessagePortMessageFilter* filter) = 0; +}; + +} // namespace android_webview + +#endif // ANDROID_WEBVIEW_BROWSER_AW_MESSAGE_PORT_SERVICE_H_
diff --git a/android_webview/browser/jni_dependency_factory.h b/android_webview/browser/jni_dependency_factory.h index 983ef2a..d27e9b2 100644 --- a/android_webview/browser/jni_dependency_factory.h +++ b/android_webview/browser/jni_dependency_factory.h
@@ -16,6 +16,7 @@ namespace android_webview { class AwBrowserContext; +class AwMessagePortService; class AwQuotaManagerBridge; class AwWebPreferencesPopulater; @@ -29,6 +30,7 @@ virtual content::WebContentsViewDelegate* CreateViewDelegate( content::WebContents* web_contents) = 0; virtual AwWebPreferencesPopulater* CreateWebPreferencesPopulater() = 0; + virtual AwMessagePortService* CreateAwMessagePortService() = 0; #if defined(VIDEO_HOLE) virtual content::ExternalVideoSurfaceContainer* CreateExternalVideoSurfaceContainer(content::WebContents* contents) = 0;
diff --git a/android_webview/browser/net/aw_url_request_context_getter.cc b/android_webview/browser/net/aw_url_request_context_getter.cc index 52b7329..e0f9013 100644 --- a/android_webview/browser/net/aw_url_request_context_getter.cc +++ b/android_webview/browser/net/aw_url_request_context_getter.cc
@@ -21,6 +21,7 @@ #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_auth_request_handler.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_interceptor.h" +#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h" #include "content/public/browser/browser_thread.h" @@ -201,33 +202,10 @@ AwBrowserContext* browser_context = AwBrowserContext::GetDefault(); DCHECK(browser_context); - // Compression statistics are not gathered for WebView, so - // DataReductionProxyStatisticsPrefs is not instantiated and passed to the - // network delegate. - DataReductionProxySettings* data_reduction_proxy_settings = - browser_context->GetDataReductionProxySettings(); - DCHECK(data_reduction_proxy_settings); - data_reduction_proxy_auth_request_handler_.reset( - new data_reduction_proxy::DataReductionProxyAuthRequestHandler( - data_reduction_proxy::Client::WEBVIEW_ANDROID, - data_reduction_proxy_settings->params(), - BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO))); - - data_reduction_proxy::DataReductionProxyNetworkDelegate* - data_reduction_proxy_network_delegate = - new data_reduction_proxy::DataReductionProxyNetworkDelegate( - aw_network_delegate.Pass(), - data_reduction_proxy_settings->params(), - data_reduction_proxy_auth_request_handler_.get(), - base::Bind( - &data_reduction_proxy::DataReductionProxyConfigurator:: - GetProxyConfigOnIOThread, - base::Unretained( - browser_context->GetDataReductionProxyConfigurator()))); - data_reduction_proxy_network_delegate->InitProxyConfigOverrider( - base::Bind(data_reduction_proxy::OnResolveProxyHandler)); - - builder.set_network_delegate(data_reduction_proxy_network_delegate); + builder.set_network_delegate( + browser_context->GetDataReductionProxyIOData()->CreateNetworkDelegate( + aw_network_delegate.Pass(), + false /* No UMA is produced to track bypasses. */ ).release()); #if !defined(DISABLE_FTP_SUPPORT) builder.set_ftp_enabled(false); // Android WebView does not support ftp yet. #endif @@ -268,10 +246,8 @@ request_interceptors_.Pass()); job_factory_.reset(new net::URLRequestInterceptingJobFactory( - job_factory_.Pass(), make_scoped_ptr( - new data_reduction_proxy::DataReductionProxyInterceptor( - data_reduction_proxy_settings->params(), NULL, - browser_context->GetDataReductionProxyEventStore())))); + job_factory_.Pass(), + browser_context->GetDataReductionProxyIOData()->CreateInterceptor())); url_request_context_->set_job_factory(job_factory_.get()); }
diff --git a/android_webview/common/android_webview_message_generator.h b/android_webview/common/android_webview_message_generator.h index 1ac28dc7..f5dcce80 100644 --- a/android_webview/common/android_webview_message_generator.h +++ b/android_webview/common/android_webview_message_generator.h
@@ -4,5 +4,6 @@ // Multiply-included file, hence no include guard. +#include "android_webview/common/aw_message_port_messages.h" #include "android_webview/common/print_messages.h" #include "android_webview/common/render_view_messages.h"
diff --git a/android_webview/common/aw_message_port_messages.h b/android_webview/common/aw_message_port_messages.h new file mode 100644 index 0000000..866d713 --- /dev/null +++ b/android_webview/common/aw_message_port_messages.h
@@ -0,0 +1,32 @@ +// Copyright 2015 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. + +// Multiply-included file, no traditional include guard. +#include <vector> + +#include "base/basictypes.h" +#include "ipc/ipc_message_macros.h" + +#define IPC_MESSAGE_START AwMessagePortMsgStart + +//----------------------------------------------------------------------------- +// MessagePort messages +// These are messages sent from the browser to the renderer process. + +// Tells the renderer to convert the sent message from a WebSerializeScript +// format to a base::ListValue. Due to the complexities of renderer/browser +// relation, this can only be done in renderer for now. +IPC_MESSAGE_ROUTED3(AwMessagePortMsg_Message, + int /* recipient message port id */, + base::string16 /* message */, + std::vector<int> /* sent message port_ids */) + +//----------------------------------------------------------------------------- +// These are messages sent from the renderer to the browser process. + +// Response to AwMessagePortMessage_ConvertMessage +IPC_MESSAGE_ROUTED3(AwMessagePortHostMsg_ConvertedMessage, + int /* recipient message port id */, + base::ListValue /* converted message */, + std::vector<int> /* sent message port_ids */)
diff --git a/android_webview/java/src/org/chromium/android_webview/AwBrowserContext.java b/android_webview/java/src/org/chromium/android_webview/AwBrowserContext.java index 77ad0ba..36463ed 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwBrowserContext.java +++ b/android_webview/java/src/org/chromium/android_webview/AwBrowserContext.java
@@ -28,6 +28,7 @@ private AwFormDatabase mFormDatabase; private HttpAuthDatabase mHttpAuthDatabase; private DefaultAndroidKeyStore mLocalKeyStore; + private AwMessagePortService mMessagePortService; public AwBrowserContext(SharedPreferences sharedPreferences) { mSharedPreferences = sharedPreferences; @@ -68,6 +69,13 @@ return mLocalKeyStore; } + public AwMessagePortService createMessagePortService() { + if (mMessagePortService == null) { + mMessagePortService = new AwMessagePortService(); + } + return mMessagePortService; + } + /** * @see android.webkit.WebView#pauseTimers() */
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContents.java b/android_webview/java/src/org/chromium/android_webview/AwContents.java index 4d80be7..70393519 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwContents.java +++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java
@@ -1790,9 +1790,16 @@ * message ports to pass. */ public void postMessageToFrame(String frameName, String message, - String sourceOrigin, String targetOrigin, int[] msgPorts) { + String sourceOrigin, String targetOrigin, MessagePort[] msgPorts) { + if (isDestroyed()) return; + int[] portIds = null; + if (msgPorts != null) { + portIds = new int[msgPorts.length]; + for (int i = 0; i < msgPorts.length; i++) + portIds[i] = msgPorts[i].portId(); + } nativePostMessageToFrame(mNativeAwContents, frameName, message, sourceOrigin, - targetOrigin, msgPorts); + targetOrigin, portIds); } /** @@ -1801,10 +1808,12 @@ * @param callback The message channel created. */ public void createMessageChannel(ValueCallback<MessageChannel> callback) { + if (isDestroyed()) return; + // Make sure the message port service is created. + mBrowserContext.createMessagePortService(); nativeCreateMessageChannel(mNativeAwContents, callback); } - //-------------------------------------------------------------------------------------------- // View and ViewGroup method implementations //-------------------------------------------------------------------------------------------- @@ -2217,12 +2226,6 @@ } } - @CalledByNative - private static void onMessageChannelCreated(int portId1, int portId2, - ValueCallback<MessageChannel> callback) { - callback.onReceiveValue(new MessageChannel(portId1, portId2)); - } - // ------------------------------------------------------------------------------------------- // Helper methods // -------------------------------------------------------------------------------------------
diff --git a/android_webview/java/src/org/chromium/android_webview/AwMessagePortService.java b/android_webview/java/src/org/chromium/android_webview/AwMessagePortService.java new file mode 100644 index 0000000..2f34e25 --- /dev/null +++ b/android_webview/java/src/org/chromium/android_webview/AwMessagePortService.java
@@ -0,0 +1,139 @@ +// Copyright 2015 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.android_webview; + +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.util.SparseArray; +import android.webkit.ValueCallback; + +import org.chromium.base.CalledByNative; +import org.chromium.base.JNINamespace; + +/** + * Provides the Message Channel functionality for Android Webview. Specifically + * manages the message ports that are associated with a message channel and + * handles posting/receiving messages to/from them. + * See https://html.spec.whatwg.org/multipage/comms.html#messagechannel for + * further information on message channels. + * + * The message ports have unique IDs. In Android webview implementation, + * the message ports are only known by their IDs at the native side. + * At the java side, the embedder deals with MessagePort objects. The mapping + * from an ID to an object is in AwMessagePortService. AwMessagePortService + * keeps a strong ref to MessagePort objects until they are closed. + * + * Ownership: The Java AwMessagePortService is owned by Java AwBrowserContext. + * The native AwMessagePortService is owned by native AwBrowserContext. The + * native peer maintains a weak ref to the java object and deregisters itself + * before being deleted. + * + * All methods are called on UI thread except as noted. + */ +@JNINamespace("android_webview") +public class AwMessagePortService { + + private static final String TAG = "AwMessagePortService"; + + private static final int POST_MESSAGE = 1; + + // TODO(sgurun) implement transferring ports from JS to Java using message channels. + private static class PostMessage { + public MessagePort port; + public String message; + + public PostMessage(MessagePort port, String message) { + this.port = port; + this.message = message; + } + } + + // The messages from JS to Java are posted to a message port on a background thread. + // We do this to make any potential synchronization between Java and JS + // easier for user programs. + private static class MessageHandlerThread extends Thread { + private static class MessageHandler extends Handler { + @Override + public void handleMessage(Message msg) { + if (msg.what == POST_MESSAGE) { + PostMessage m = (PostMessage) msg.obj; + m.port.onMessage(m.message); + return; + } + throw new IllegalStateException("undefined message"); + } + } + + private MessageHandler mHandler; + + public Handler getHandler() { + return mHandler; + } + + public void run() { + Looper.prepare(); + mHandler = new MessageHandler(); + Looper.loop(); + } + } + + // A thread safe storage for Message Ports. + private static class MessagePortStorage { + private SparseArray<MessagePort> mMessagePorts = new SparseArray<MessagePort>(); + private Object mLock = new Object(); + + public void put(int portId, MessagePort m) { + synchronized (mLock) { + mMessagePorts.put(portId, m); + } + } + public MessagePort get(int portId) { + synchronized (mLock) { + return mMessagePorts.get(portId); + } + } + } + + private long mNativeMessagePortService; + private MessagePortStorage mPortStorage = new MessagePortStorage(); + private MessageHandlerThread mMessageHandlerThread = new MessageHandlerThread(); + + AwMessagePortService() { + mNativeMessagePortService = nativeInitAwMessagePortService(); + mMessageHandlerThread.start(); + } + + private MessagePort addPort(int portId) { + if (mPortStorage.get(portId) != null) { + throw new IllegalStateException("Port already exists"); + } + MessagePort m = new MessagePort(portId); + mPortStorage.put(portId, m); + return m; + } + + @CalledByNative + private void onMessageChannelCreated(int portId1, int portId2, + ValueCallback<MessageChannel> callback) { + callback.onReceiveValue(new MessageChannel(addPort(portId1), addPort(portId2))); + } + + // Called on IO thread. + @CalledByNative + private void onPostMessage(int portId, String message, int[] ports) { + PostMessage m = new PostMessage(mPortStorage.get(portId), message); + Handler handler = mMessageHandlerThread.getHandler(); + Message msg = handler.obtainMessage(POST_MESSAGE, m); + handler.sendMessage(msg); + } + + @CalledByNative + private void unregisterNativeAwMessagePortService() { + mNativeMessagePortService = 0; + } + + private native long nativeInitAwMessagePortService(); +}
diff --git a/android_webview/java/src/org/chromium/android_webview/MessageChannel.java b/android_webview/java/src/org/chromium/android_webview/MessageChannel.java index 9248624..d2957ce 100644 --- a/android_webview/java/src/org/chromium/android_webview/MessageChannel.java +++ b/android_webview/java/src/org/chromium/android_webview/MessageChannel.java
@@ -9,20 +9,20 @@ * http://www.whatwg.org/specs/web-apps/current-work/multipage/web-messaging.html#message-channels */ public class MessageChannel { - // The message port IDs of port1 and port2. - private int mPort1; - private int mPort2; + // The message ports of MessageChannel. + private MessagePort mPort1; + private MessagePort mPort2; - public MessageChannel(int port1, int port2) { + public MessageChannel(MessagePort port1, MessagePort port2) { mPort1 = port1; mPort2 = port2; } - public int port1() { + public MessagePort port1() { return mPort1; } - public int port2() { + public MessagePort port2() { return mPort2; } }
diff --git a/android_webview/java/src/org/chromium/android_webview/MessagePort.java b/android_webview/java/src/org/chromium/android_webview/MessagePort.java new file mode 100644 index 0000000..ef0e8d77 --- /dev/null +++ b/android_webview/java/src/org/chromium/android_webview/MessagePort.java
@@ -0,0 +1,46 @@ +// Copyright 2015 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.android_webview; + +import android.util.Log; + +/** + * Represents the MessageChannel MessagePort object. Inspired from + * http://www.whatwg.org/specs/web-apps/current-work/multipage/web-messaging.html#message-channels + */ +public class MessagePort { + + /** + * The interface for message handler for receiving messages. Called on a background thread. + */ + public static interface MessageHandler { + void onMessage(String message); + }; + + private static final String TAG = "AwMessagePortService"; + + private int mPortId; + private MessageHandler mHandler; + + public MessagePort(int portId) { + mPortId = portId; + } + + public int portId() { + return mPortId; + } + + public void setMessageHandler(MessageHandler handler) { + mHandler = handler; + } + + public void onMessage(String message) { + if (mHandler == null) { + Log.w(TAG, "No handler set for port [" + mPortId + "], dropping message " + message); + return; + } + mHandler.onMessage(message); + } +}
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/PostMessageTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/PostMessageTest.java index 7d7ea86..3be279c9 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/PostMessageTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/PostMessageTest.java
@@ -13,6 +13,7 @@ import org.chromium.android_webview.AwContents; import org.chromium.android_webview.MessageChannel; +import org.chromium.android_webview.MessagePort; import org.chromium.android_webview.test.util.CommonResources; import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.MinAndroidSdkLevel; @@ -25,12 +26,11 @@ public class PostMessageTest extends AwTestBase { private static final String SOURCE_ORIGIN = "android_webview"; + // Timeout to failure, in milliseconds + private static final long TIMEOUT = scaleTimeout(5000); // Inject to the page to verify received messages. private static class MessageObject { - // Timeout to failure, in milliseconds - private static final long TIMEOUT = scaleTimeout(5000); - private boolean mReady; private String mData; private String mOrigin; @@ -102,12 +102,16 @@ } private static final String WEBVIEW_MESSAGE = "from_webview"; + private static final String JS_MESSAGE = "from_js"; private static final String TEST_PAGE = "<!DOCTYPE html><html><body>" + " <script type=\"text/javascript\">" + " onmessage = function (e) {" + " messageObject.setMessageParams(e.data, e.origin, e.ports);" + + " if (e.ports != null && e.ports.length > 0) {" + + " e.ports[0].postMessage(\"" + JS_MESSAGE + "\");" + + " }" + " }" + " </script>" + "</body></html>"; @@ -137,22 +141,61 @@ assertEquals(SOURCE_ORIGIN, mMessageObject.getOrigin()); } - // TODO(sgurun) This test verifies a channel is created by posting one of the - // ports of the channel to a MessagePort and verifying one port is received. - // in a next CL we will update the JS to post messages back to Webview so - // we could do a more thorough verification. + private static class ChannelContainer { + private boolean mReady; + private MessageChannel mChannel; + private Object mLock = new Object(); + private String mMessage; + + public void set(MessageChannel channel) { + mChannel = channel; + } + public MessageChannel get() { + return mChannel; + } + + public void setMessage(String message) { + synchronized (mLock) { + mMessage = message; + mReady = true; + mLock.notify(); + } + } + + public String getMessage() { + return mMessage; + } + + public void waitForMessage() throws InterruptedException { + synchronized (mLock) { + if (!mReady) mLock.wait(TIMEOUT); + } + } + } + + // Verify that a channel can be created and basic full duplex communication + // can happen on it. @SmallTest @Feature({"AndroidWebView", "Android-PostMessage"}) public void testCreateChannel() throws Throwable { loadPage(TEST_PAGE); + final ChannelContainer channelContainer = new ChannelContainer(); runTestOnUiThread(new Runnable() { @Override public void run() { ValueCallback<MessageChannel> callback = new ValueCallback<MessageChannel>() { @Override public void onReceiveValue(MessageChannel channel) { + // verify communication from JS to Java. + channelContainer.set(channel); + channel.port1().setMessageHandler(new MessagePort.MessageHandler() { + @Override + public void onMessage(String message) { + channelContainer.setMessage(message); + } + }); mAwContents.postMessageToFrame(null, WEBVIEW_MESSAGE, SOURCE_ORIGIN, - mWebServer.getBaseUrl(), new int[]{channel.port2()}); + mWebServer.getBaseUrl(), new MessagePort[]{channel.port2()}); } }; mAwContents.createMessageChannel(callback); @@ -161,8 +204,21 @@ mMessageObject.waitForMessage(); assertEquals(WEBVIEW_MESSAGE, mMessageObject.getData()); assertEquals(SOURCE_ORIGIN, mMessageObject.getOrigin()); - // verify that one message port is received. + // verify that one message port is received at the js side assertEquals(1, mMessageObject.getPorts().length); + // wait until we receive a message from JS + runTestOnUiThread(new Runnable() { + @Override + public void run() { + try { + channelContainer.waitForMessage(); + } catch (InterruptedException e) { + // ignore. + } + } + }); + assertEquals(JS_MESSAGE, channelContainer.getMessage()); + // TODO(sgurun) verify communication from Java to JS on the created channel } private static final String WORKER_MESSAGE = "from_worker"; @@ -211,7 +267,7 @@ public void onReceiveValue(MessageChannel channel) { mAwContents.postMessageToFrame(null, WEBVIEW_MESSAGE, SOURCE_ORIGIN, mWebServer.getBaseUrl(), - new int[]{channel.port1(), channel.port2()}); + new MessagePort[]{channel.port1(), channel.port2()}); } }; mAwContents.createMessageChannel(callback);
diff --git a/android_webview/lib/main/aw_main_delegate.cc b/android_webview/lib/main/aw_main_delegate.cc index c996cc43..8ad76578 100644 --- a/android_webview/lib/main/aw_main_delegate.cc +++ b/android_webview/lib/main/aw_main_delegate.cc
@@ -10,6 +10,7 @@ #include "android_webview/lib/aw_browser_dependency_factory_impl.h" #include "android_webview/native/aw_assets.h" #include "android_webview/native/aw_media_url_interceptor.h" +#include "android_webview/native/aw_message_port_service_impl.h" #include "android_webview/native/aw_quota_manager_bridge_impl.h" #include "android_webview/native/aw_web_contents_view_delegate.h" #include "android_webview/native/aw_web_preferences_populater_impl.h" @@ -60,7 +61,6 @@ base::CommandLine* cl = base::CommandLine::ForCurrentProcess(); cl->AppendSwitch(switches::kEnableBeginFrameScheduling); - cl->AppendSwitch(switches::kEnableImplSidePainting); // WebView uses the Android system's scrollbars and overscroll glow. cl->AppendSwitch(switches::kDisableOverscrollEdgeEffect); @@ -172,6 +172,10 @@ return new AwWebPreferencesPopulaterImpl(); } +AwMessagePortService* AwMainDelegate::CreateAwMessagePortService() { + return new AwMessagePortServiceImpl(); +} + #if defined(VIDEO_HOLE) content::ExternalVideoSurfaceContainer* AwMainDelegate::CreateExternalVideoSurfaceContainer(
diff --git a/android_webview/lib/main/aw_main_delegate.h b/android_webview/lib/main/aw_main_delegate.h index ebf25fc..167d9219 100644 --- a/android_webview/lib/main/aw_main_delegate.h +++ b/android_webview/lib/main/aw_main_delegate.h
@@ -30,23 +30,23 @@ private: // content::ContentMainDelegate implementation: - virtual bool BasicStartupComplete(int* exit_code) override; - virtual void PreSandboxStartup() override; - virtual void SandboxInitialized(const std::string& process_type) override; - virtual int RunProcess( + bool BasicStartupComplete(int* exit_code) override; + void PreSandboxStartup() override; + void SandboxInitialized(const std::string& process_type) override; + int RunProcess( const std::string& process_type, const content::MainFunctionParams& main_function_params) override; - virtual void ProcessExiting(const std::string& process_type) override; - virtual content::ContentBrowserClient* CreateContentBrowserClient() override; - virtual content::ContentRendererClient* - CreateContentRendererClient() override; + void ProcessExiting(const std::string& process_type) override; + content::ContentBrowserClient* CreateContentBrowserClient() override; + content::ContentRendererClient* CreateContentRendererClient() override; // JniDependencyFactory implementation. - virtual scoped_refptr<AwQuotaManagerBridge> CreateAwQuotaManagerBridge( + scoped_refptr<AwQuotaManagerBridge> CreateAwQuotaManagerBridge( AwBrowserContext* browser_context) override; - virtual content::WebContentsViewDelegate* CreateViewDelegate( + content::WebContentsViewDelegate* CreateViewDelegate( content::WebContents* web_contents) override; - virtual AwWebPreferencesPopulater* CreateWebPreferencesPopulater() override; + AwWebPreferencesPopulater* CreateWebPreferencesPopulater() override; + AwMessagePortService* CreateAwMessagePortService() override; #if defined(VIDEO_HOLE) virtual content::ExternalVideoSurfaceContainer* CreateExternalVideoSurfaceContainer(
diff --git a/android_webview/native/android_webview_jni_registrar.cc b/android_webview/native/android_webview_jni_registrar.cc index 253a070..e81853f2 100644 --- a/android_webview/native/android_webview_jni_registrar.cc +++ b/android_webview/native/android_webview_jni_registrar.cc
@@ -14,6 +14,7 @@ #include "android_webview/native/aw_dev_tools_server.h" #include "android_webview/native/aw_form_database.h" #include "android_webview/native/aw_http_auth_handler.h" +#include "android_webview/native/aw_message_port_service_impl.h" #include "android_webview/native/aw_pdf_exporter.h" #include "android_webview/native/aw_picture.h" #include "android_webview/native/aw_quota_manager_bridge_impl.h" @@ -58,6 +59,7 @@ { "AwWebResourceResponseImpl", RegisterAwWebResourceResponse }, { "InputStream", RegisterInputStream }, { "JavaBrowserViewRendererHelper", RegisterJavaBrowserViewRendererHelper }, + { "AwMessagePortService", RegisterAwMessagePortService }, }; bool RegisterJni(JNIEnv* env) {
diff --git a/android_webview/native/aw_autofill_client.cc b/android_webview/native/aw_autofill_client.cc index b14b24ee..c0427fa 100644 --- a/android_webview/native/aw_autofill_client.cc +++ b/android_webview/native/aw_autofill_client.cc
@@ -66,8 +66,12 @@ AwContentBrowserClient::GetAwBrowserContext()); } +IdentityProvider* AwAutofillClient::GetIdentityProvider() { + return nullptr; +} + autofill::PersonalDataManager* AwAutofillClient::GetPersonalDataManager() { - return NULL; + return nullptr; } scoped_refptr<autofill::AutofillWebDataService>
diff --git a/android_webview/native/aw_autofill_client.h b/android_webview/native/aw_autofill_client.h index 11085f4..dd85587 100644 --- a/android_webview/native/aw_autofill_client.h +++ b/android_webview/native/aw_autofill_client.h
@@ -60,6 +60,7 @@ virtual scoped_refptr<autofill::AutofillWebDataService> GetDatabase() override; virtual PrefService* GetPrefs() override; + IdentityProvider* GetIdentityProvider() override; virtual void HideRequestAutocompleteDialog() override; virtual void ShowAutofillSettings() override; virtual void ShowUnmaskPrompt(
diff --git a/android_webview/native/aw_contents.cc b/android_webview/native/aw_contents.cc index 2a9a35f..64cd9a9 100644 --- a/android_webview/native/aw_contents.cc +++ b/android_webview/native/aw_contents.cc
@@ -21,6 +21,7 @@ #include "android_webview/native/aw_browser_dependency_factory.h" #include "android_webview/native/aw_contents_client_bridge.h" #include "android_webview/native/aw_contents_io_thread_client_impl.h" +#include "android_webview/native/aw_message_port_service_impl.h" #include "android_webview/native/aw_pdf_exporter.h" #include "android_webview/native/aw_picture.h" #include "android_webview/native/aw_web_contents_delegate.h" @@ -133,23 +134,6 @@ render_process_id, render_frame_id); } -void OnMessageChannelCreated(ScopedJavaGlobalRef<jobject>* callback, - int* port1, - int* port2) { - JNIEnv* env = AttachCurrentThread(); - Java_AwContents_onMessageChannelCreated(env, *port1, *port2, - callback->obj()); -} - -void PostMessageToFrameOnIOThread(WebContents* web_contents, - base::string16* source_origin, - base::string16* target_origin, - base::string16* data, - std::vector<int>* ports) { - content::MessagePortProvider::PostMessageToFrame(web_contents, - *source_origin, *target_origin, *data, *ports); -} - } // namespace // static @@ -1084,49 +1068,40 @@ jstring frame_name, jstring message, jstring source_origin, jstring target_origin, jintArray msgPorts) { - base::string16* j_source_origin = new base::string16; - ConvertJavaStringToUTF16(env, source_origin, j_source_origin); - base::string16* j_target_origin = new base::string16; - ConvertJavaStringToUTF16(env, target_origin, j_target_origin); - base::string16* j_message = new base::string16; - ConvertJavaStringToUTF16(env, message, j_message); - std::vector<int>* j_ports = new std::vector<int>; - + base::string16 j_source_origin(ConvertJavaStringToUTF16(env, source_origin)); + base::string16 j_target_origin(ConvertJavaStringToUTF16(env, target_origin)); + base::string16 j_message(ConvertJavaStringToUTF16(env, message)); + std::vector<int> j_ports; if (msgPorts != nullptr) - base::android::JavaIntArrayToIntVector(env, msgPorts, j_ports); + base::android::JavaIntArrayToIntVector(env, msgPorts, &j_ports); - BrowserThread::PostTask( - BrowserThread::IO, - FROM_HERE, - base::Bind(&PostMessageToFrameOnIOThread, - web_contents_.get(), - base::Owned(j_source_origin), - base::Owned(j_target_origin), - base::Owned(j_message), - base::Owned(j_ports))); + content::MessagePortProvider::PostMessageToFrame(web_contents_.get(), + j_source_origin, + j_target_origin, + j_message, + j_ports); +} + +scoped_refptr<AwMessagePortMessageFilter> +AwContents::GetMessagePortMessageFilter() { + // Create a message port message filter if necessary + if (message_port_message_filter_.get() == nullptr) { + message_port_message_filter_ = + new AwMessagePortMessageFilter( + web_contents_->GetMainFrame()->GetRoutingID()); + web_contents_->GetRenderProcessHost()->AddFilter( + message_port_message_filter_.get()); + } + return message_port_message_filter_; } void AwContents::CreateMessageChannel(JNIEnv* env, jobject obj, jobject callback) { - ScopedJavaGlobalRef<jobject>* j_callback = new ScopedJavaGlobalRef<jobject>(); - j_callback->Reset(env, callback); - int* port1 = new int; - int* port2 = new int; - BrowserThread::PostTaskAndReply( - BrowserThread::IO, - FROM_HERE, - base::Bind(&content::MessagePortProvider::CreateMessageChannel, - web_contents_.get(), - port1, - port2), - base::Bind(&OnMessageChannelCreated, - base::Owned(j_callback), - base::Owned(port1), - base::Owned(port2))); + AwMessagePortServiceImpl::GetInstance()->CreateMessageChannel(env, callback, + GetMessagePortMessageFilter()); } - void SetShouldDownloadFavicons(JNIEnv* env, jclass jclazz) { g_should_download_favicons = true; }
diff --git a/android_webview/native/aw_contents.h b/android_webview/native/aw_contents.h index 4a4afbb..13ad67ce 100644 --- a/android_webview/native/aw_contents.h +++ b/android_webview/native/aw_contents.h
@@ -11,6 +11,7 @@ #include <utility> #include "android_webview/browser/aw_browser_permission_request_delegate.h" +#include "android_webview/browser/aw_message_port_message_filter.h" #include "android_webview/browser/browser_view_renderer.h" #include "android_webview/browser/browser_view_renderer_client.h" #include "android_webview/browser/find_helper.h" @@ -220,6 +221,7 @@ void SetJsOnlineProperty(JNIEnv* env, jobject obj, jboolean network_up); void TrimMemory(JNIEnv* env, jobject obj, jint level, jboolean visible); + scoped_refptr<AwMessagePortMessageFilter> GetMessagePortMessageFilter(); void PostMessageToFrame(JNIEnv* env, jobject obj, jstring frame_id, jstring message, jstring source_origin, jstring target_origin, jintArray msgPorts); @@ -244,6 +246,7 @@ BrowserViewRenderer browser_view_renderer_; scoped_ptr<AwPdfExporter> pdf_exporter_; scoped_ptr<PermissionRequestHandler> permission_request_handler_; + scoped_refptr<AwMessagePortMessageFilter> message_port_message_filter_; // GURL is supplied by the content layer as requesting frame. // Callback is supplied by the content layer, and is invoked with the result
diff --git a/android_webview/native/aw_message_port_service_impl.cc b/android_webview/native/aw_message_port_service_impl.cc new file mode 100644 index 0000000..5fa4e1b4 --- /dev/null +++ b/android_webview/native/aw_message_port_service_impl.cc
@@ -0,0 +1,161 @@ +// Copyright 2015 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 "android_webview/native/aw_message_port_service_impl.h" + +#include "android_webview/browser/aw_browser_context.h" +#include "android_webview/browser/aw_message_port_message_filter.h" +#include "android_webview/native/aw_contents.h" +#include "base/android/jni_array.h" +#include "base/android/jni_string.h" +#include "base/bind.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/message_port_provider.h" +#include "jni/AwMessagePortService_jni.h" + +namespace android_webview { + +using base::android::AttachCurrentThread; +using base::android::ConvertUTF16ToJavaString; +using base::android::ScopedJavaGlobalRef; +using base::android::ScopedJavaLocalRef; +using base::android::ToJavaIntArray; +using content::BrowserThread; +using content::MessagePortProvider; + +//static +AwMessagePortServiceImpl* AwMessagePortServiceImpl::GetInstance() { + return static_cast<AwMessagePortServiceImpl*>( + AwBrowserContext::GetDefault()->GetMessagePortService()); +} + +AwMessagePortServiceImpl::AwMessagePortServiceImpl() { +} + +AwMessagePortServiceImpl::~AwMessagePortServiceImpl() { + JNIEnv* env = AttachCurrentThread(); + ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); + if (obj.is_null()) + return; + Java_AwMessagePortService_unregisterNativeAwMessagePortService(env, + obj.obj()); +} + +void AwMessagePortServiceImpl::Init(JNIEnv* env, jobject obj) { + java_ref_ = JavaObjectWeakGlobalRef(env, obj); +} + +void AwMessagePortServiceImpl::CreateMessageChannel( + JNIEnv* env, + jobject callback, + scoped_refptr<AwMessagePortMessageFilter> filter) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + + ScopedJavaGlobalRef<jobject>* j_callback = new ScopedJavaGlobalRef<jobject>(); + j_callback->Reset(env, callback); + + int* portId1 = new int; + int* portId2 = new int; + BrowserThread::PostTaskAndReply( + BrowserThread::IO, + FROM_HERE, + base::Bind(&AwMessagePortServiceImpl::CreateMessageChannelOnIOThread, + base::Unretained(this), + filter, + portId1, + portId2), + base::Bind(&AwMessagePortServiceImpl::OnMessageChannelCreated, + base::Unretained(this), + base::Owned(j_callback), + base::Owned(portId1), + base::Owned(portId2))); +} + +void AwMessagePortServiceImpl::OnConvertedMessage( + int message_port_id, + const base::ListValue& message, + const std::vector<int>& sent_message_port_ids) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + JNIEnv* env = AttachCurrentThread(); + ScopedJavaLocalRef<jobject> jobj = java_ref_.get(env); + if (jobj.is_null()) + return; + + if (message.GetSize() != 1) { + NOTREACHED(); + return; + } + + base::string16 value; + if (!message.GetString(0, &value)) { + LOG(WARNING) << "Converting post message to a string failed for port " + << message_port_id; + return; + } + ScopedJavaLocalRef<jstring> jmsg = ConvertUTF16ToJavaString(env, value); + ScopedJavaLocalRef<jintArray> jports = + ToJavaIntArray(env, sent_message_port_ids); + Java_AwMessagePortService_onPostMessage(env, + jobj.obj(), + message_port_id, + jmsg.obj(), + jports.obj()); +} + +void AwMessagePortServiceImpl::OnMessagePortMessageFilterClosing( + AwMessagePortMessageFilter* filter) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + for (MessagePorts::iterator iter = ports_.begin(); + iter != ports_.end(); iter++) { + if (iter->second == filter) { + ports_.erase(iter); + } + } +} + +void AwMessagePortServiceImpl::CreateMessageChannelOnIOThread( + scoped_refptr<AwMessagePortMessageFilter> filter, + int* portId1, + int* portId2) { + content::MessagePortProvider::CreateMessageChannel(filter.get(), portId1, + portId2); + AddPort(*portId1, filter.get()); + AddPort(*portId2, filter.get()); +} + +void AwMessagePortServiceImpl::OnMessageChannelCreated( + ScopedJavaGlobalRef<jobject>* callback, + int* port1, + int* port2) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + JNIEnv* env = AttachCurrentThread(); + ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); + if (obj.is_null()) + return; + Java_AwMessagePortService_onMessageChannelCreated(env, obj.obj(), *port1, + *port2, callback->obj()); +} + +void AwMessagePortServiceImpl::AddPort(int message_port_id, + AwMessagePortMessageFilter* filter) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + if (ports_.count(message_port_id)) { + NOTREACHED(); + return; + } + ports_[message_port_id] = filter; +} + +bool RegisterAwMessagePortService(JNIEnv* env) { + return RegisterNativesImpl(env); +} + +// static +jlong InitAwMessagePortService(JNIEnv* env, jobject obj) { + AwMessagePortServiceImpl* service = AwMessagePortServiceImpl::GetInstance(); + service->Init(env, obj); + return reinterpret_cast<intptr_t>(service); +} + +} // namespace android_webview
diff --git a/android_webview/native/aw_message_port_service_impl.h b/android_webview/native/aw_message_port_service_impl.h new file mode 100644 index 0000000..d938b6eb --- /dev/null +++ b/android_webview/native/aw_message_port_service_impl.h
@@ -0,0 +1,65 @@ +// Copyright 2015 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 ANDROID_WEBVIEW_NATIVE_AW_MESSAGE_PORT_SERVICE_IMPL_H_ +#define ANDROID_WEBVIEW_NATIVE_AW_MESSAGE_PORT_SERVICE_IMPL_H_ + +#include <jni.h> +#include <map> + +#include "android_webview/browser/aw_message_port_service.h" +#include "base/android/jni_weak_ref.h" +#include "base/basictypes.h" +#include "base/memory/ref_counted.h" +#include "base/strings/string16.h" + +namespace android_webview { + +// This class is the native peer of AwMessagePortService.java. Please see the +// java class for an explanation of use, ownership and lifetime. + +// Threading: Created and initialized on UI thread. For other methods, see +// the method level DCHECKS or documentation. +class AwMessagePortServiceImpl : public AwMessagePortService { + public: + static AwMessagePortServiceImpl* GetInstance(); + + AwMessagePortServiceImpl(); + ~AwMessagePortServiceImpl(); + void Init(JNIEnv* env, jobject object); + + void CreateMessageChannel(JNIEnv* env, jobject callback, + scoped_refptr<AwMessagePortMessageFilter> filter); + + // AwMessagePortService implementation + void OnConvertedMessage( + int message_port_id, + const base::ListValue& message, + const std::vector<int>& sent_message_port_ids) override; + void OnMessagePortMessageFilterClosing( + AwMessagePortMessageFilter* filter) override; + +private: + void CreateMessageChannelOnIOThread( + scoped_refptr<AwMessagePortMessageFilter> filter, + int* port1, + int* port2); + void OnMessageChannelCreated( + base::android::ScopedJavaGlobalRef<jobject>* callback, + int* port1, + int* port2); + void AddPort(int message_port_id, AwMessagePortMessageFilter* filter); + + JavaObjectWeakGlobalRef java_ref_; + typedef std::map<int, AwMessagePortMessageFilter*> MessagePorts; + MessagePorts ports_; // Access on IO thread + + DISALLOW_COPY_AND_ASSIGN(AwMessagePortServiceImpl); +}; + +bool RegisterAwMessagePortService(JNIEnv* env); + +} // namespace android_webview + +#endif // ANDROID_WEBVIEW_NATIVE_AW_MESSAGE_PORT_SERVICE_IMPL_H_
diff --git a/android_webview/native/webview_native.gyp b/android_webview/native/webview_native.gyp index 52b3e455..34889e17 100644 --- a/android_webview/native/webview_native.gyp +++ b/android_webview/native/webview_native.gyp
@@ -58,6 +58,8 @@ 'aw_http_auth_handler.h', 'aw_media_url_interceptor.cc', 'aw_media_url_interceptor.h', + 'aw_message_port_service_impl.cc', + 'aw_messagE_port_service_impl.h', 'aw_pdf_exporter.cc', 'aw_pdf_exporter.h', 'aw_picture.cc', @@ -131,6 +133,7 @@ '../java/src/org/chromium/android_webview/AwDevToolsServer.java', '../java/src/org/chromium/android_webview/AwFormDatabase.java', '../java/src/org/chromium/android_webview/AwHttpAuthHandler.java', + '../java/src/org/chromium/android_webview/AwMessagePortService.java', '../java/src/org/chromium/android_webview/AwPdfExporter.java', '../java/src/org/chromium/android_webview/AwPicture.java', '../java/src/org/chromium/android_webview/AwQuotaManagerBridge.java',
diff --git a/android_webview/renderer/DEPS b/android_webview/renderer/DEPS index 055b5e0..6c1ad13 100644 --- a/android_webview/renderer/DEPS +++ b/android_webview/renderer/DEPS
@@ -20,4 +20,6 @@ "+ui/gfx", "+ui/gl/gpu_memory_buffer.h", + + "+v8/include/v8.h", ]
diff --git a/android_webview/renderer/aw_content_renderer_client.cc b/android_webview/renderer/aw_content_renderer_client.cc index 24349cd..37710597 100644 --- a/android_webview/renderer/aw_content_renderer_client.cc +++ b/android_webview/renderer/aw_content_renderer_client.cc
@@ -8,6 +8,7 @@ #include "android_webview/common/render_view_messages.h" #include "android_webview/common/url_constants.h" #include "android_webview/renderer/aw_key_systems.h" +#include "android_webview/renderer/aw_message_port_client.h" #include "android_webview/renderer/aw_permission_client.h" #include "android_webview/renderer/aw_render_frame_ext.h" #include "android_webview/renderer/aw_render_view_ext.h" @@ -122,6 +123,7 @@ new AwPermissionClient(render_frame); new PrintRenderFrameObserver(render_frame); new AwRenderFrameExt(render_frame); + new AwMessagePortClient(render_frame); // TODO(jam): when the frame tree moves into content and parent() works at // RenderFrame construction, simplify this by just checking parent().
diff --git a/android_webview/renderer/aw_message_port_client.cc b/android_webview/renderer/aw_message_port_client.cc new file mode 100644 index 0000000..c96f322 --- /dev/null +++ b/android_webview/renderer/aw_message_port_client.cc
@@ -0,0 +1,70 @@ +// Copyright 2015 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 "android_webview/renderer/aw_message_port_client.h" + +#include "android_webview/common/aw_message_port_messages.h" +#include "content/public/renderer/render_frame.h" +#include "content/public/renderer/render_view.h" +#include "content/public/renderer/v8_value_converter.h" +#include "ipc/ipc_message_macros.h" +#include "third_party/WebKit/public/web/WebFrame.h" +#include "third_party/WebKit/public/web/WebKit.h" +#include "third_party/WebKit/public/web/WebSerializedScriptValue.h" +#include "third_party/WebKit/public/web/WebView.h" +#include "v8/include/v8.h" + +using blink::WebSerializedScriptValue; +using content::V8ValueConverter; +using std::vector; + +namespace android_webview { + +AwMessagePortClient::AwMessagePortClient(content::RenderFrame* render_frame) + : content::RenderFrameObserver(render_frame) { +} + +AwMessagePortClient::~AwMessagePortClient() { +} + +bool AwMessagePortClient::OnMessageReceived( + const IPC::Message& message) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(AwMessagePortClient, message) + IPC_MESSAGE_HANDLER(AwMessagePortMsg_Message, OnPostMessage) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + + return handled; +} + +void AwMessagePortClient::OnPostMessage( + int message_port_id, + const base::string16& message, + const vector<int>& sent_message_port_ids) { + v8::HandleScope handle_scope(blink::mainThreadIsolate()); + blink::WebFrame* main_frame = + render_frame()->GetRenderView()->GetWebView()->mainFrame(); + if (main_frame == nullptr) { + return; + } + v8::Local<v8::Context> context = main_frame->mainWorldScriptContext(); + v8::Context::Scope context_scope(context); + DCHECK(!context.IsEmpty()); + WebSerializedScriptValue v = WebSerializedScriptValue::fromString(message); + v8::Handle<v8::Value> v8value = v.deserialize(); + + scoped_ptr<V8ValueConverter> converter; + converter.reset(V8ValueConverter::create()); + converter->SetDateAllowed(true); + converter->SetRegExpAllowed(true); + base::ListValue result; + result.Append(converter->FromV8Value(v8value, context)); + Send(new AwMessagePortHostMsg_ConvertedMessage(render_frame()->GetRoutingID(), + message_port_id, + result, + sent_message_port_ids)); +} + +}
diff --git a/android_webview/renderer/aw_message_port_client.h b/android_webview/renderer/aw_message_port_client.h new file mode 100644 index 0000000..f3a337b --- /dev/null +++ b/android_webview/renderer/aw_message_port_client.h
@@ -0,0 +1,35 @@ +// Copyright 2015 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 ANDROID_WEBVIEW_RENDERER_AW_MESSAGE_PORT_CLIENT_H_ +#define ANDROID_WEBVIEW_RENDERER_AW_MESSAGE_PORT_CLIENT_H_ + +#include <vector> + +#include "base/strings/string16.h" +#include "content/public/renderer/render_frame_observer.h" + +namespace android_webview { + +// Renderer side of Android webview specific message port service. This service +// is used to convert messages from WebSerializedScriptValue to a base value. +class AwMessagePortClient : public content::RenderFrameObserver { + public: + explicit AwMessagePortClient(content::RenderFrame* render_frame); + + private: + virtual ~AwMessagePortClient(); + + // RenderFrameObserver + bool OnMessageReceived(const IPC::Message& message) override; + + void OnPostMessage(int message_port_id, + const base::string16& message, + const std::vector<int>& sent_message_port_ids); + DISALLOW_COPY_AND_ASSIGN(AwMessagePortClient); +}; + +} + +#endif // ANDROID_WEBVIEW_RENDERER_AW_MESSAGE_PORT_CLIENT_H_
diff --git a/android_webview/renderer/print_web_view_helper.cc b/android_webview/renderer/print_web_view_helper.cc index d334764..f47916dd 100644 --- a/android_webview/renderer/print_web_view_helper.cc +++ b/android_webview/renderer/print_web_view_helper.cc
@@ -36,6 +36,7 @@ #include "third_party/WebKit/public/web/WebPluginDocument.h" #include "third_party/WebKit/public/web/WebPrintParams.h" #include "third_party/WebKit/public/web/WebPrintScalingOption.h" +#include "third_party/WebKit/public/web/WebSandboxFlags.h" #include "third_party/WebKit/public/web/WebScriptSource.h" #include "third_party/WebKit/public/web/WebSettings.h" #include "third_party/WebKit/public/web/WebView.h" @@ -540,8 +541,13 @@ virtual void didStopLoading(); // blink::WebFrameClient override: + // TODO(alexmos): Remove once Blink is updated to use sandbox flags. virtual blink::WebFrame* createChildFrame(blink::WebLocalFrame* parent, const blink::WebString& name); + virtual blink::WebFrame* createChildFrame( + blink::WebLocalFrame* parent, + const blink::WebString& name, + blink::WebSandboxFlags sandboxFlags); virtual void frameDetached(blink::WebFrame* frame); private: @@ -682,9 +688,17 @@ weak_ptr_factory_.GetWeakPtr())); } +// TODO(alexmos): Remove once Blink is updated to use sandbox flags. blink::WebFrame* PrepareFrameAndViewForPrint::createChildFrame( blink::WebLocalFrame* parent, const blink::WebString& name) { + return createChildFrame(parent, name, blink::WebSandboxFlags::None); +} + +blink::WebFrame* PrepareFrameAndViewForPrint::createChildFrame( + blink::WebLocalFrame* parent, + const blink::WebString& name, + blink::WebSandboxFlags sandboxFlags) { blink::WebFrame* frame = blink::WebLocalFrame::create(this); parent->appendChild(frame); return frame;
diff --git a/ash/accelerators/accelerator_controller.cc b/ash/accelerators/accelerator_controller.cc index c951f2e..5900769 100644 --- a/ash/accelerators/accelerator_controller.cc +++ b/ash/accelerators/accelerator_controller.cc
@@ -1218,8 +1218,8 @@ case POWER_PRESSED: // fallthrough case POWER_RELEASED: if (!base::SysInfo::IsRunningOnChromeOS()) { - // There is no powerd in linux desktop, so call the - // PowerButtonController here. + // There is no powerd, the Chrome OS power manager, in linux desktop, + // so call the PowerButtonController here. Shell::GetInstance()->power_button_controller()-> OnPowerButtonEvent(action == POWER_PRESSED, base::TimeTicks()); }
diff --git a/ash/ash.gyp b/ash/ash.gyp index a93aa58..cd614a6 100644 --- a/ash/ash.gyp +++ b/ash/ash.gyp
@@ -508,8 +508,6 @@ 'wm/gestures/overview_gesture_handler.h', 'wm/gestures/shelf_gesture_handler.cc', 'wm/gestures/shelf_gesture_handler.h', - 'wm/gestures/tray_gesture_handler.cc', - 'wm/gestures/tray_gesture_handler.h', 'wm/immersive_fullscreen_controller.cc', 'wm/immersive_fullscreen_controller.h', 'wm/immersive_revealed_lock.cc', @@ -539,6 +537,10 @@ 'wm/overlay_event_filter.cc', 'wm/overlay_event_filter.h', 'wm/overview/overview_animation_type.h', + 'wm/overview/overview_window_button.h', + 'wm/overview/overview_window_button.cc', + 'wm/overview/overview_window_targeter.h', + 'wm/overview/overview_window_targeter.cc', 'wm/overview/scoped_overview_animation_settings.h', 'wm/overview/scoped_overview_animation_settings.cc', 'wm/overview/scoped_transform_overview_window.cc', @@ -551,11 +553,8 @@ 'wm/window_cycle_controller.h', 'wm/window_cycle_list.cc', 'wm/window_cycle_list.h', - 'wm/overview/transparent_activate_window_button.cc', - 'wm/overview/transparent_activate_window_button.h', 'wm/overview/window_selector_controller.cc', 'wm/overview/window_selector_controller.h', - 'wm/overview/window_selector_delegate.h', 'wm/overview/window_selector_item.cc', 'wm/overview/window_selector_item.h', 'wm/panels/attached_panel_window_targeter.cc',
diff --git a/ash/ash_switches.cc b/ash/ash_switches.cc index 4eab689..637d7d0 100644 --- a/ash/ash_switches.cc +++ b/ash/ash_switches.cc
@@ -71,9 +71,6 @@ // ChromeVox is enabled or not. const char kAshEnableSystemSounds[] = "ash-enable-system-sounds"; -// Enables showing the tray bubble by dragging on the shelf. -const char kAshEnableTrayDragging[] = "ash-enable-tray-dragging"; - // Hides notifications that are irrelevant to Chrome OS device factory testing, // such as battery level updates. const char kAshHideNotificationsForFactory[] =
diff --git a/ash/ash_switches.h b/ash/ash_switches.h index 6a3e18f5..9562beb 100644 --- a/ash/ash_switches.h +++ b/ash/ash_switches.h
@@ -33,7 +33,6 @@ ASH_EXPORT extern const char kAshEnableSoftwareMirroring[]; ASH_EXPORT extern const char kAshEnableSystemSounds[]; ASH_EXPORT extern const char kAshEnableTouchViewTesting[]; -ASH_EXPORT extern const char kAshEnableTrayDragging[]; ASH_EXPORT extern const char kAshHideNotificationsForFactory[]; ASH_EXPORT extern const char kAshHostWindowBounds[]; ASH_EXPORT extern const char kAshSecondaryDisplayLayout[];
diff --git a/ash/content/display/screen_orientation_controller_chromeos.cc b/ash/content/display/screen_orientation_controller_chromeos.cc index 297455d..1480cfb 100644 --- a/ash/content/display/screen_orientation_controller_chromeos.cc +++ b/ash/content/display/screen_orientation_controller_chromeos.cc
@@ -15,8 +15,10 @@ #include "content/public/browser/screen_orientation_provider.h" #include "content/public/browser/web_contents.h" #include "ui/aura/window.h" +#include "ui/aura/window_observer.h" #include "ui/gfx/display.h" #include "ui/gfx/geometry/size.h" +#include "ui/wm/public/activation_client.h" namespace { @@ -61,8 +63,7 @@ namespace ash { ScreenOrientationController::ScreenOrientationController() - : locking_window_(NULL), - natural_orientation_(GetDisplayNaturalOrientation()), + : natural_orientation_(GetDisplayNaturalOrientation()), ignore_display_configuration_updates_(false), rotation_locked_(false), user_rotation_(gfx::Display::ROTATE_0), @@ -76,6 +77,9 @@ Shell::GetInstance()->RemoveShellObserver(this); chromeos::AccelerometerReader::GetInstance()->RemoveObserver(this); Shell::GetInstance()->display_controller()->RemoveObserver(this); + Shell::GetInstance()->activation_client()->RemoveObserver(this); + for (auto& windows : locking_windows_) + windows.first->RemoveObserver(this); } void ScreenOrientationController::AddObserver(Observer* observer) { @@ -113,6 +117,30 @@ rotation); } +void ScreenOrientationController::OnWindowActivated(aura::Window* gained_active, + aura::Window* lost_active) { + ApplyLockForActiveWindow(); +} + +// Currently contents::WebContents will only be able to lock rotation while +// fullscreen. In this state a user cannot click on the tab strip to change. If +// this becomes supported for non-fullscreen tabs then the following interferes +// with TabDragController. OnWindowVisibilityChanged is called between a mouse +// down and mouse up. The rotation this triggers leads to a coordinate space +// change in the middle of an event. Causes the tab to separate from the tab +// strip. +void ScreenOrientationController::OnWindowVisibilityChanged( + aura::Window* window, + bool visible) { + if (locking_windows_.find(window) == locking_windows_.end()) + return; + ApplyLockForActiveWindow(); +} + +void ScreenOrientationController::OnWindowDestroying(aura::Window* window) { + RemoveLockingWindow(window); +} + void ScreenOrientationController::OnAccelerometerUpdated( const ui::AccelerometerUpdate& update) { if (rotation_locked_) @@ -135,18 +163,80 @@ void ScreenOrientationController::Lock( content::WebContents* web_contents, blink::WebScreenOrientationLockType lock_orientation) { - aura::Window* requesting_window = web_contents->GetNativeView(); - // TODO(jonross): Track one rotation lock per window. When the active window - // changes apply any corresponding rotation lock. - if (!locking_window_) - locking_window_ = requesting_window; - else if (requesting_window != locking_window_) - return; + if (locking_windows_.empty()) + Shell::GetInstance()->activation_client()->AddObserver(this); + aura::Window* requesting_window = web_contents->GetNativeView(); + if (!requesting_window->HasObserver(this)) + requesting_window->AddObserver(this); + locking_windows_[requesting_window] = lock_orientation; + + ApplyLockForActiveWindow(); +} + +bool ScreenOrientationController::ScreenOrientationProviderSupported() { + return Shell::GetInstance() + ->maximize_mode_controller() + ->IsMaximizeModeWindowManagerEnabled() && + base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kAshEnableTouchViewTesting); +} + +void ScreenOrientationController::Unlock(content::WebContents* web_contents) { + aura::Window* requesting_window = web_contents->GetNativeView(); + RemoveLockingWindow(requesting_window); +} + +void ScreenOrientationController::OnDisplayConfigurationChanged() { + if (ignore_display_configuration_updates_) + return; + gfx::Display::Rotation user_rotation = + Shell::GetInstance() + ->display_manager() + ->GetDisplayInfo(gfx::Display::InternalDisplayId()) + .rotation(); + if (user_rotation != current_rotation_) { + // A user may change other display configuration settings. When the user + // does change the rotation setting, then lock rotation to prevent the + // accelerometer from erasing their change. + SetRotationLocked(true); + user_rotation_ = current_rotation_ = user_rotation; + } +} + +void ScreenOrientationController::OnMaximizeModeStarted() { + DisplayManager* display_manager = Shell::GetInstance()->display_manager(); + if (!display_manager->HasInternalDisplay()) + return; + current_rotation_ = user_rotation_ = + display_manager->GetDisplayInfo(gfx::Display::InternalDisplayId()) + .rotation(); + if (!rotation_locked_) + LoadDisplayRotationProperties(); + chromeos::AccelerometerReader::GetInstance()->AddObserver(this); + Shell::GetInstance()->display_controller()->AddObserver(this); +} + +void ScreenOrientationController::OnMaximizeModeEnded() { + if (!Shell::GetInstance()->display_manager()->HasInternalDisplay()) + return; + chromeos::AccelerometerReader::GetInstance()->RemoveObserver(this); + Shell::GetInstance()->display_controller()->RemoveObserver(this); + if (current_rotation_ != user_rotation_) + SetDisplayRotation(user_rotation_); +} + +void ScreenOrientationController::LockRotation( + gfx::Display::Rotation rotation) { + SetRotationLocked(true); + SetDisplayRotation(rotation); +} + +void ScreenOrientationController::LockRotationToOrientation( + blink::WebScreenOrientationLockType lock_orientation) { switch (lock_orientation) { case blink::WebScreenOrientationLockAny: SetRotationLocked(false); - locking_window_ = NULL; break; case blink::WebScreenOrientationLockDefault: NOTREACHED(); @@ -179,66 +269,6 @@ } } -bool ScreenOrientationController::ScreenOrientationProviderSupported() { - return Shell::GetInstance() - ->maximize_mode_controller() - ->IsMaximizeModeWindowManagerEnabled() && - base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kAshEnableTouchViewTesting); -} - -void ScreenOrientationController::Unlock(content::WebContents* web_contents) { - aura::Window* requesting_window = web_contents->GetNativeView(); - if (requesting_window != locking_window_) - return; - locking_window_ = NULL; - SetRotationLocked(false); -} - -void ScreenOrientationController::OnDisplayConfigurationChanged() { - if (ignore_display_configuration_updates_) - return; - gfx::Display::Rotation user_rotation = - Shell::GetInstance() - ->display_manager() - ->GetDisplayInfo(gfx::Display::InternalDisplayId()) - .rotation(); - if (user_rotation != current_rotation_) { - // A user may change other display configuration settings. When the user - // does change the rotation setting, then lock rotation to prevent the - // accelerometer from erasing their change. - SetRotationLocked(true); - user_rotation_ = current_rotation_ = user_rotation; - } -} - -void ScreenOrientationController::OnMaximizeModeStarted() { - DisplayManager* display_manager = Shell::GetInstance()->display_manager(); - if (!display_manager->HasInternalDisplay()) - return; - current_rotation_ = user_rotation_ = - display_manager->GetDisplayInfo(gfx::Display::InternalDisplayId()) - .rotation(); - LoadDisplayRotationProperties(); - chromeos::AccelerometerReader::GetInstance()->AddObserver(this); - Shell::GetInstance()->display_controller()->AddObserver(this); -} - -void ScreenOrientationController::OnMaximizeModeEnded() { - if (!Shell::GetInstance()->display_manager()->HasInternalDisplay()) - return; - chromeos::AccelerometerReader::GetInstance()->RemoveObserver(this); - Shell::GetInstance()->display_controller()->RemoveObserver(this); - if (current_rotation_ != user_rotation_) - SetDisplayRotation(user_rotation_); -} - -void ScreenOrientationController::LockRotation( - gfx::Display::Rotation rotation) { - SetRotationLocked(true); - SetDisplayRotation(rotation); -} - void ScreenOrientationController::LockRotationToPrimaryOrientation( blink::WebScreenOrientationLockType lock_orientation) { LockRotation(natural_orientation_ == lock_orientation @@ -339,4 +369,25 @@ SetRotationLocked(true); } +void ScreenOrientationController::ApplyLockForActiveWindow() { + aura::Window* active_window = + Shell::GetInstance()->activation_client()->GetActiveWindow(); + for (auto const& windows : locking_windows_) { + if (windows.first->TargetVisibility() && + active_window->Contains(windows.first)) { + LockRotationToOrientation(windows.second); + return; + } + } + SetRotationLocked(false); +} + +void ScreenOrientationController::RemoveLockingWindow(aura::Window* window) { + locking_windows_.erase(window); + if (locking_windows_.empty()) + Shell::GetInstance()->activation_client()->RemoveObserver(this); + window->RemoveObserver(this); + ApplyLockForActiveWindow(); +} + } // namespace ash
diff --git a/ash/content/display/screen_orientation_controller_chromeos.h b/ash/content/display/screen_orientation_controller_chromeos.h index 362e1311..82ff208 100644 --- a/ash/content/display/screen_orientation_controller_chromeos.h +++ b/ash/content/display/screen_orientation_controller_chromeos.h
@@ -5,6 +5,8 @@ #ifndef ASH_CONTENT_DISPLAY_SCREEN_ORIENTATION_CONTROLLER_CHROMEOS_H_ #define ASH_CONTENT_DISPLAY_SCREEN_ORIENTATION_CONTROLLER_CHROMEOS_H_ +#include <map> + #include "ash/ash_export.h" #include "ash/display/display_controller.h" #include "ash/shell_observer.h" @@ -13,7 +15,9 @@ #include "chromeos/accelerometer/accelerometer_reader.h" #include "content/public/browser/screen_orientation_delegate.h" #include "third_party/WebKit/public/platform/WebScreenOrientationLockType.h" +#include "ui/aura/window_observer.h" #include "ui/gfx/display.h" +#include "ui/wm/public/activation_change_observer.h" namespace aura { class Window; @@ -27,7 +31,9 @@ // Implements ChromeOS specific functionality for ScreenOrientationProvider. class ASH_EXPORT ScreenOrientationController - : public chromeos::AccelerometerReader::Observer, + : public aura::client::ActivationChangeObserver, + public aura::WindowObserver, + public chromeos::AccelerometerReader::Observer, public content::ScreenOrientationDelegate, public DisplayController::Observer, public ShellObserver { @@ -65,6 +71,14 @@ // Sets the display rotation and suppresses display notifications. void SetDisplayRotation(gfx::Display::Rotation rotation); + // aura::client::ActivationChangeObserver: + void OnWindowActivated(aura::Window* gained_active, + aura::Window* lost_active) override; + + // aura::WindowObserver: + void OnWindowVisibilityChanged(aura::Window* window, bool visible) override; + void OnWindowDestroying(aura::Window* window) override; + // chromeos::AccelerometerReader::Observer: void OnAccelerometerUpdated(const ui::AccelerometerUpdate& update) override; @@ -88,6 +102,12 @@ // the rotation lock. void LockRotation(gfx::Display::Rotation rotation); + // Sets the display rotation based on |lock_orientation|. Future accelerometer + // updates should not be used to change the rotation. SetRotationLocked(false) + // removes the rotation lock. + void LockRotationToOrientation( + blink::WebScreenOrientationLockType lock_orientation); + // Locks rotation to the angle matching the primary orientation for // |lock_orientation|. void LockRotationToPrimaryOrientation( @@ -112,9 +132,12 @@ // preferences. These are then applied. void LoadDisplayRotationProperties(); - // The window that has applied the current lock. No other window can apply a - // lock until the current window unlocks rotation. - aura::Window* locking_window_; + // Determines the rotation lock, and orientation, for the currently active + // window, and applies it. If there is none, rotation lock will be removed. + void ApplyLockForActiveWindow(); + + // Removes a window and its locking preference. + void RemoveLockingWindow(aura::Window* window); // The orientation of the display when at a rotation of 0. blink::WebScreenOrientationLockType natural_orientation_; @@ -137,6 +160,10 @@ // Rotation Lock observers. ObserverList<Observer> observers_; + // Tracks all windows that have requested a lock, as well as the requested + // orientation. + std::map<aura::Window*, blink::WebScreenOrientationLockType> locking_windows_; + DISALLOW_COPY_AND_ASSIGN(ScreenOrientationController); };
diff --git a/ash/content/display/screen_orientation_controller_chromeos_unittest.cc b/ash/content/display/screen_orientation_controller_chromeos_unittest.cc index 54e590ee..69dbd076 100644 --- a/ash/content/display/screen_orientation_controller_chromeos_unittest.cc +++ b/ash/content/display/screen_orientation_controller_chromeos_unittest.cc
@@ -19,11 +19,13 @@ #include "content/public/browser/web_contents.h" #include "content/public/test/test_browser_context.h" #include "third_party/WebKit/public/platform/WebScreenOrientationLockType.h" +#include "ui/aura/window.h" #include "ui/gfx/display.h" #include "ui/message_center/message_center.h" #include "ui/views/test/webview_test_helper.h" #include "ui/views/view.h" #include "ui/views/views_delegate.h" +#include "ui/wm/public/activation_client.h" namespace ash { @@ -75,6 +77,23 @@ update); } +// Attaches the NativeView of |web_contents| to |parent| without changing the +// currently active window. +void AttachWebContents(content::WebContents* web_contents, + aura::Window* parent) { + aura::Window* window = web_contents->GetNativeView(); + window->Show(); + parent->AddChild(window); +} + +// Attaches the NativeView of |web_contents| to |parent|, ensures that it is +// visible, and activates the parent window. +void AttachAndActivateWebContents(content::WebContents* web_contents, + aura::Window* parent) { + AttachWebContents(web_contents, parent); + Shell::GetInstance()->activation_client()->ActivateWindow(parent); +} + } // namespace class ScreenOrientationControllerTest : public test::AshTestBase { @@ -143,10 +162,12 @@ // Tests that a content::WebContents can lock rotation. TEST_F(ScreenOrientationControllerTest, LockOrientation) { scoped_ptr<content::WebContents> content(CreateWebContents()); + scoped_ptr<aura::Window> focus_window(CreateTestWindowInShellWithId(0)); ASSERT_NE(nullptr, content->GetNativeView()); ASSERT_EQ(gfx::Display::ROTATE_0, Rotation()); ASSERT_FALSE(RotationLocked()); + AttachAndActivateWebContents(content.get(), focus_window.get()); delegate()->Lock(content.get(), blink::WebScreenOrientationLockLandscape); EXPECT_EQ(gfx::Display::ROTATE_0, Rotation()); EXPECT_TRUE(RotationLocked()); @@ -155,10 +176,12 @@ // Tests that a content::WebContents can unlock rotation. TEST_F(ScreenOrientationControllerTest, Unlock) { scoped_ptr<content::WebContents> content(CreateWebContents()); + scoped_ptr<aura::Window> focus_window(CreateTestWindowInShellWithId(0)); ASSERT_NE(nullptr, content->GetNativeView()); ASSERT_EQ(gfx::Display::ROTATE_0, Rotation()); ASSERT_FALSE(RotationLocked()); + AttachAndActivateWebContents(content.get(), focus_window.get()); delegate()->Lock(content.get(), blink::WebScreenOrientationLockLandscape); EXPECT_EQ(gfx::Display::ROTATE_0, Rotation()); EXPECT_TRUE(RotationLocked()); @@ -171,10 +194,12 @@ // display after having locked rotation. TEST_F(ScreenOrientationControllerTest, OrientationChanges) { scoped_ptr<content::WebContents> content(CreateWebContents()); + scoped_ptr<aura::Window> focus_window(CreateTestWindowInShellWithId(0)); ASSERT_NE(nullptr, content->GetNativeView()); ASSERT_EQ(gfx::Display::ROTATE_0, Rotation()); ASSERT_FALSE(RotationLocked()); + AttachAndActivateWebContents(content.get(), focus_window.get()); delegate()->Lock(content.get(), blink::WebScreenOrientationLockPortrait); EXPECT_EQ(gfx::Display::ROTATE_90, Rotation()); EXPECT_TRUE(RotationLocked()); @@ -183,23 +208,17 @@ EXPECT_EQ(gfx::Display::ROTATE_0, Rotation()); } -// Tests that a user initiated rotation lock cannot be unlocked by a -// content::WebContents. -TEST_F(ScreenOrientationControllerTest, UserLockRejectsUnlock) { - delegate()->SetRotationLocked(true); - - scoped_ptr<content::WebContents> content(CreateWebContents()); - delegate()->Unlock(content.get()); - EXPECT_TRUE(RotationLocked()); -} - // Tests that orientation can only be set by the first content::WebContents that // has set a rotation lock. TEST_F(ScreenOrientationControllerTest, SecondContentCannotChangeOrientation) { scoped_ptr<content::WebContents> content1(CreateWebContents()); scoped_ptr<content::WebContents> content2(CreateSecondaryWebContents()); + scoped_ptr<aura::Window> focus_window1(CreateTestWindowInShellWithId(0)); + scoped_ptr<aura::Window> focus_window2(CreateTestWindowInShellWithId(1)); ASSERT_NE(content1->GetNativeView(), content2->GetNativeView()); + AttachAndActivateWebContents(content1.get(), focus_window1.get()); + AttachWebContents(content2.get(), focus_window2.get()); delegate()->Lock(content1.get(), blink::WebScreenOrientationLockLandscape); delegate()->Lock(content2.get(), blink::WebScreenOrientationLockPortrait); EXPECT_EQ(gfx::Display::ROTATE_0, Rotation()); @@ -210,25 +229,101 @@ TEST_F(ScreenOrientationControllerTest, SecondContentCannotUnlock) { scoped_ptr<content::WebContents> content1(CreateWebContents()); scoped_ptr<content::WebContents> content2(CreateSecondaryWebContents()); + scoped_ptr<aura::Window> focus_window1(CreateTestWindowInShellWithId(0)); + scoped_ptr<aura::Window> focus_window2(CreateTestWindowInShellWithId(1)); ASSERT_NE(content1->GetNativeView(), content2->GetNativeView()); + AttachAndActivateWebContents(content1.get(), focus_window1.get()); + AttachWebContents(content2.get(), focus_window2.get()); delegate()->Lock(content1.get(), blink::WebScreenOrientationLockLandscape); delegate()->Unlock(content2.get()); EXPECT_TRUE(RotationLocked()); } -// Tests that alternate content::WebContents can set a rotation lock after a -// preexisting lock has been released. -TEST_F(ScreenOrientationControllerTest, AfterUnlockSecondContentCanLock) { +// Tests that a rotation lock is applied only while the content::WebContents are +// a part of the active window. +TEST_F(ScreenOrientationControllerTest, ActiveWindowChangesUpdateLock) { + scoped_ptr<content::WebContents> content(CreateWebContents()); + scoped_ptr<aura::Window> focus_window1(CreateTestWindowInShellWithId(0)); + scoped_ptr<aura::Window> focus_window2(CreateTestWindowInShellWithId(1)); + + AttachAndActivateWebContents(content.get(), focus_window1.get()); + delegate()->Lock(content.get(), blink::WebScreenOrientationLockLandscape); + ASSERT_TRUE(RotationLocked()); + + aura::client::ActivationClient* activation_client = + Shell::GetInstance()->activation_client(); + activation_client->ActivateWindow(focus_window2.get()); + EXPECT_FALSE(RotationLocked()); + + activation_client->ActivateWindow(focus_window1.get()); + EXPECT_TRUE(RotationLocked()); +} + +// Tests that switching between windows with different orientation locks change +// the orientation. +TEST_F(ScreenOrientationControllerTest, ActiveWindowChangesUpdateOrientation) { scoped_ptr<content::WebContents> content1(CreateWebContents()); scoped_ptr<content::WebContents> content2(CreateSecondaryWebContents()); - ASSERT_NE(content1->GetNativeView(), content2->GetNativeView()); + scoped_ptr<aura::Window> focus_window1(CreateTestWindowInShellWithId(0)); + scoped_ptr<aura::Window> focus_window2(CreateTestWindowInShellWithId(1)); + AttachAndActivateWebContents(content1.get(), focus_window1.get()); + AttachWebContents(content2.get(), focus_window2.get()); delegate()->Lock(content1.get(), blink::WebScreenOrientationLockLandscape); - delegate()->Unlock(content1.get()); delegate()->Lock(content2.get(), blink::WebScreenOrientationLockPortrait); - EXPECT_EQ(gfx::Display::ROTATE_90, Rotation()); + EXPECT_EQ(gfx::Display::ROTATE_0, GetInternalDisplayRotation()); + + aura::client::ActivationClient* activation_client = + Shell::GetInstance()->activation_client(); + activation_client->ActivateWindow(focus_window2.get()); EXPECT_TRUE(RotationLocked()); + EXPECT_EQ(gfx::Display::ROTATE_90, GetInternalDisplayRotation()); + + activation_client->ActivateWindow(focus_window1.get()); + EXPECT_TRUE(RotationLocked()); + EXPECT_EQ(gfx::Display::ROTATE_0, GetInternalDisplayRotation()); +} + +// Tests that a rotation lock is removed when the setting window is hidden, and +// that it is reapplied when the window becomes visible. +TEST_F(ScreenOrientationControllerTest, VisibilityChangesLock) { + scoped_ptr<content::WebContents> content(CreateWebContents()); + scoped_ptr<aura::Window> focus_window(CreateTestWindowInShellWithId(0)); + AttachAndActivateWebContents(content.get(), focus_window.get()); + delegate()->Lock(content.get(), blink::WebScreenOrientationLockLandscape); + EXPECT_TRUE(RotationLocked()); + + aura::Window* window = content->GetNativeView(); + window->Hide(); + EXPECT_FALSE(RotationLocked()); + + window->Show(); + EXPECT_TRUE(RotationLocked()); +} + +// Tests that when a window is destroyed that its rotation lock is removed, and +// window activations no longer change the lock +TEST_F(ScreenOrientationControllerTest, WindowDestructionRemovesLock) { + scoped_ptr<content::WebContents> content(CreateWebContents()); + scoped_ptr<aura::Window> focus_window1(CreateTestWindowInShellWithId(0)); + scoped_ptr<aura::Window> focus_window2(CreateTestWindowInShellWithId(1)); + + AttachAndActivateWebContents(content.get(), focus_window1.get()); + delegate()->Lock(content.get(), blink::WebScreenOrientationLockLandscape); + ASSERT_TRUE(RotationLocked()); + + focus_window1->RemoveChild(content->GetNativeView()); + content.reset(); + EXPECT_FALSE(RotationLocked()); + + aura::client::ActivationClient* activation_client = + Shell::GetInstance()->activation_client(); + activation_client->ActivateWindow(focus_window2.get()); + EXPECT_FALSE(RotationLocked()); + + activation_client->ActivateWindow(focus_window1.get()); + EXPECT_FALSE(RotationLocked()); } // Tests that accelerometer readings in each of the screen angles will trigger a
diff --git a/ash/desktop_background/desktop_background_view.cc b/ash/desktop_background/desktop_background_view.cc index 4ffc3e1..43e5f18 100644 --- a/ash/desktop_background/desktop_background_view.cc +++ b/ash/desktop_background/desktop_background_view.cc
@@ -22,6 +22,7 @@ #include "ui/aura/window_event_dispatcher.h" #include "ui/compositor/layer.h" #include "ui/gfx/canvas.h" +#include "ui/gfx/geometry/safe_integer_conversions.h" #include "ui/gfx/geometry/size_conversions.h" #include "ui/gfx/image/image.h" #include "ui/gfx/transform.h" @@ -36,11 +37,6 @@ namespace ash { namespace { -// For our scaling ratios we need to round positive numbers. -int RoundPositive(double x) { - return static_cast<int>(floor(x + 0.5)); -} - // A view that controls the child view's layer so that the layer // always has the same size as the display's original, un-scaled size // in DIP. The layer then transformed to fit to the virtual screen @@ -63,7 +59,7 @@ float ui_scale = info.GetEffectiveUIScale(); gfx::SizeF pixel_size = display.size(); pixel_size.Scale(1.0f / ui_scale); - gfx::Size rounded_size = gfx::ToCeiledSize(pixel_size); + gfx::Size rounded_size = gfx::ToFlooredSize(pixel_size); DCHECK_EQ(1, child_count()); views::View* child = child_at(0); child->SetBounds(0, 0, rounded_size.width(), rounded_size.height()); @@ -169,11 +165,12 @@ gfx::Size cropped_size; if (vertical_ratio > horizontal_ratio) { cropped_size = gfx::Size( - RoundPositive(static_cast<double>(width()) / vertical_ratio), + gfx::ToFlooredInt(static_cast<double>(width()) / vertical_ratio), wallpaper.height()); } else { - cropped_size = gfx::Size(wallpaper.width(), - RoundPositive(static_cast<double>(height()) / horizontal_ratio)); + cropped_size = gfx::Size( + wallpaper.width(), + gfx::ToFlooredInt(static_cast<double>(height()) / horizontal_ratio)); } gfx::Rect wallpaper_cropped_rect(
diff --git a/ash/drag_drop/drag_drop_controller.cc b/ash/drag_drop/drag_drop_controller.cc index 695c7737..1c53068 100644 --- a/ash/drag_drop/drag_drop_controller.cc +++ b/ash/drag_drop/drag_drop_controller.cc
@@ -9,6 +9,7 @@ #include "ash/shell.h" #include "base/bind.h" #include "base/message_loop/message_loop.h" +#include "base/metrics/histogram_macros.h" #include "base/run_loop.h" #include "ui/aura/client/capture_client.h" #include "ui/aura/env.h" @@ -159,6 +160,9 @@ provider->GetDragImage().size().IsEmpty()) return 0; + UMA_HISTOGRAM_ENUMERATION("Event.DragDrop.Start", source, + ui::DragDropTypes::DRAG_EVENT_SOURCE_COUNT); + current_drag_event_source_ = source; DragDropTracker* tracker = new DragDropTracker(root_window, drag_drop_window_delegate_.get()); @@ -222,6 +226,14 @@ run_loop.Run(); } + if (drag_operation_ == 0) { + UMA_HISTOGRAM_ENUMERATION("Event.DragDrop.Cancel", source, + ui::DragDropTypes::DRAG_EVENT_SOURCE_COUNT); + } else { + UMA_HISTOGRAM_ENUMERATION("Event.DragDrop.Drop", source, + ui::DragDropTypes::DRAG_EVENT_SOURCE_COUNT); + } + if (!cancel_animation_.get() || !cancel_animation_->is_animating() || !pending_long_tap_.get()) { // If drag cancel animation is running, this cleanup is done when the @@ -482,9 +494,9 @@ drag_image_.reset(); if (pending_long_tap_) { // If not in a nested message loop, we can forward the long tap right now. - if (!should_block_during_drag_drop_) + if (!should_block_during_drag_drop_) { ForwardPendingLongTap(); - else { + } else { // See comment about this in OnGestureEvent(). base::MessageLoopForUI::current()->PostTask( FROM_HERE,
diff --git a/ash/shelf/alternate_app_list_button.cc b/ash/shelf/alternate_app_list_button.cc deleted file mode 100644 index 247f506..0000000 --- a/ash/shelf/alternate_app_list_button.cc +++ /dev/null
@@ -1,171 +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 "ash/shelf/alternate_app_list_button.h" - -#include "ash/ash_constants.h" -#include "ash/ash_switches.h" -#include "ash/shelf/shelf_button.h" -#include "ash/shelf/shelf_button_host.h" -#include "ash/shelf/shelf_item_types.h" -#include "ash/shelf/shelf_layout_manager.h" -#include "ash/shelf/shelf_widget.h" -#include "ash/shell.h" -#include "grit/ash_resources.h" -#include "grit/ash_strings.h" -#include "ui/accessibility/ax_view_state.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/base/resource/resource_bundle.h" -#include "ui/compositor/layer.h" -#include "ui/compositor/layer_animation_element.h" -#include "ui/compositor/layer_animation_sequence.h" -#include "ui/compositor/scoped_layer_animation_settings.h" -#include "ui/gfx/canvas.h" -#include "ui/gfx/image/image_skia_operations.h" -#include "ui/views/controls/button/image_button.h" -#include "ui/views/painter.h" - -namespace ash { -// static -const int AlternateAppListButton::kImageBoundsSize = 7; - - -AlternateAppListButton::AlternateAppListButton(views::ButtonListener* listener, - ShelfButtonHost* host, - ShelfWidget* shelf_widget) - : views::ImageButton(listener), - host_(host), - shelf_widget_(shelf_widget) { - SetAccessibleName(l10n_util::GetStringUTF16(IDS_ASH_SHELF_APP_LIST_TITLE)); - SetSize(gfx::Size(ShelfLayoutManager::kShelfSize, - ShelfLayoutManager::kShelfSize)); - SetFocusPainter(views::Painter::CreateSolidFocusPainter( - kFocusBorderColor, gfx::Insets(1, 1, 1, 1))); -} - -AlternateAppListButton::~AlternateAppListButton() { -} - -bool AlternateAppListButton::OnMousePressed(const ui::MouseEvent& event) { - ImageButton::OnMousePressed(event); - host_->PointerPressedOnButton(this, ShelfButtonHost::MOUSE, event); - return true; -} - -void AlternateAppListButton::OnMouseReleased(const ui::MouseEvent& event) { - ImageButton::OnMouseReleased(event); - host_->PointerReleasedOnButton(this, ShelfButtonHost::MOUSE, false); -} - -void AlternateAppListButton::OnMouseCaptureLost() { - host_->PointerReleasedOnButton(this, ShelfButtonHost::MOUSE, true); - ImageButton::OnMouseCaptureLost(); -} - -bool AlternateAppListButton::OnMouseDragged(const ui::MouseEvent& event) { - ImageButton::OnMouseDragged(event); - host_->PointerDraggedOnButton(this, ShelfButtonHost::MOUSE, event); - return true; -} - -void AlternateAppListButton::OnMouseMoved(const ui::MouseEvent& event) { - ImageButton::OnMouseMoved(event); - host_->MouseMovedOverButton(this); -} - -void AlternateAppListButton::OnMouseEntered(const ui::MouseEvent& event) { - ImageButton::OnMouseEntered(event); - host_->MouseEnteredButton(this); -} - -void AlternateAppListButton::OnMouseExited(const ui::MouseEvent& event) { - ImageButton::OnMouseExited(event); - host_->MouseExitedButton(this); -} - -void AlternateAppListButton::OnGestureEvent(ui::GestureEvent* event) { - switch (event->type()) { - case ui::ET_GESTURE_SCROLL_BEGIN: - host_->PointerPressedOnButton(this, ShelfButtonHost::TOUCH, *event); - event->SetHandled(); - return; - case ui::ET_GESTURE_SCROLL_UPDATE: - host_->PointerDraggedOnButton(this, ShelfButtonHost::TOUCH, *event); - event->SetHandled(); - return; - case ui::ET_GESTURE_SCROLL_END: - case ui::ET_SCROLL_FLING_START: - host_->PointerReleasedOnButton(this, ShelfButtonHost::TOUCH, false); - event->SetHandled(); - return; - default: - ImageButton::OnGestureEvent(event); - return; - } -} - -void AlternateAppListButton::OnPaint(gfx::Canvas* canvas) { - // Call the base class first to paint any background/borders. - View::OnPaint(canvas); - - int background_image_id = 0; - if (Shell::GetInstance()->GetAppListTargetVisibility()) { - background_image_id = IDR_AURA_NOTIFICATION_BACKGROUND_PRESSED; - } else { - if (shelf_widget_->GetDimsShelf()) - background_image_id = IDR_AURA_NOTIFICATION_BACKGROUND_ON_BLACK; - else - background_image_id = IDR_AURA_NOTIFICATION_BACKGROUND_NORMAL; - } - ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - const gfx::ImageSkia* background_image = - rb.GetImageNamed(background_image_id).ToImageSkia(); - const gfx::ImageSkia* forground_image = - rb.GetImageNamed(IDR_ASH_SHELF_ICON_APPLIST_ALTERNATE).ToImageSkia(); - - gfx::Rect contents_bounds = GetContentsBounds(); - gfx::Rect background_bounds, forground_bounds; - - ShelfAlignment alignment = shelf_widget_->GetAlignment(); - background_bounds.set_size(background_image->size()); - if (alignment == SHELF_ALIGNMENT_LEFT) { - background_bounds.set_x(contents_bounds.width() - - ShelfLayoutManager::kShelfItemInset - background_image->width()); - background_bounds.set_y(contents_bounds.y() + - (contents_bounds.height() - background_image->height()) / 2); - } else if(alignment == SHELF_ALIGNMENT_RIGHT) { - background_bounds.set_x(ShelfLayoutManager::kShelfItemInset); - background_bounds.set_y(contents_bounds.y() + - (contents_bounds.height() - background_image->height()) / 2); - } else { - background_bounds.set_y(ShelfLayoutManager::kShelfItemInset); - background_bounds.set_x(contents_bounds.x() + - (contents_bounds.width() - background_image->width()) / 2); - } - - forground_bounds.set_size(forground_image->size()); - forground_bounds.set_x(background_bounds.x() + - std::max(0, - (background_bounds.width() - forground_bounds.width()) / 2)); - forground_bounds.set_y(background_bounds.y() + - std::max(0, - (background_bounds.height() - forground_bounds.height()) / 2)); - - canvas->DrawImageInt(*background_image, - background_bounds.x(), - background_bounds.y()); - canvas->DrawImageInt(*forground_image, - forground_bounds.x(), - forground_bounds.y()); - - views::Painter::PaintFocusPainter(this, canvas, focus_painter()); -} - -void AlternateAppListButton::GetAccessibleState( - ui::AXViewState* state) { - state->role = ui::AX_ROLE_BUTTON; - state->name = host_->GetAccessibleName(this); -} - -} // namespace ash
diff --git a/ash/shelf/shelf_layout_manager.cc b/ash/shelf/shelf_layout_manager.cc index b096b8f..c74103a 100644 --- a/ash/shelf/shelf_layout_manager.cc +++ b/ash/shelf/shelf_layout_manager.cc
@@ -77,12 +77,6 @@ return widget->GetNativeView()->layer(); } -bool IsDraggingTrayEnabled() { - static bool dragging_tray_allowed = base::CommandLine::ForCurrentProcess()-> - HasSwitch(ash::switches::kAshEnableTrayDragging); - return dragging_tray_allowed; -} - } // namespace // static @@ -413,29 +407,12 @@ UpdateShelfBackground(BACKGROUND_CHANGE_ANIMATE); } -ShelfLayoutManager::DragState ShelfLayoutManager::UpdateGestureDrag( +void ShelfLayoutManager::UpdateGestureDrag( const ui::GestureEvent& gesture) { bool horizontal = IsHorizontalAlignment(); gesture_drag_amount_ += horizontal ? gesture.details().scroll_y() : gesture.details().scroll_x(); LayoutShelf(); - - // Start reveling the status menu when: - // - dragging up on an already visible shelf - // - dragging up on a hidden shelf, but it is currently completely visible. - if (horizontal && gesture.details().scroll_y() < 0) { - int min_height = 0; - if (gesture_drag_auto_hide_state_ == SHELF_AUTO_HIDE_HIDDEN && shelf_) - min_height = shelf_->GetContentsView()->GetPreferredSize().height(); - - if (min_height < shelf_->GetWindowBoundsInScreen().height() && - gesture.root_location().x() >= - shelf_->status_area_widget()->GetWindowBoundsInScreen().x() && - IsDraggingTrayEnabled()) - return DRAG_TRAY; - } - - return DRAG_SHELF; } void ShelfLayoutManager::CompleteGestureDrag(const ui::GestureEvent& gesture) {
diff --git a/ash/shelf/shelf_layout_manager.h b/ash/shelf/shelf_layout_manager.h index e42df4dd..7e0118a7 100644 --- a/ash/shelf/shelf_layout_manager.h +++ b/ash/shelf/shelf_layout_manager.h
@@ -153,14 +153,7 @@ // Gesture related functions: void OnGestureEdgeSwipe(const ui::GestureEvent& gesture); void StartGestureDrag(const ui::GestureEvent& gesture); - enum DragState { - DRAG_SHELF, - DRAG_TRAY - }; - // Returns DRAG_SHELF if the gesture should continue to drag the entire shelf. - // Returns DRAG_TRAY if the gesture can start dragging the tray-bubble from - // this point on. - DragState UpdateGestureDrag(const ui::GestureEvent& gesture); + void UpdateGestureDrag(const ui::GestureEvent& gesture); void CompleteGestureDrag(const ui::GestureEvent& gesture); void CancelGestureDrag();
diff --git a/ash/shelf/shelf_layout_manager_unittest.cc b/ash/shelf/shelf_layout_manager_unittest.cc index 7d84adc..7daade7 100644 --- a/ash/shelf/shelf_layout_manager_unittest.cc +++ b/ash/shelf/shelf_layout_manager_unittest.cc
@@ -362,13 +362,6 @@ return CreateTestWidgetWithParams(params); } - // Overridden from AshTestBase: - void SetUp() override { - base::CommandLine::ForCurrentProcess()->AppendSwitch( - ash::switches::kAshEnableTrayDragging); - test::AshTestBase::SetUp(); - } - void RunGestureDragTests(gfx::Vector2d); // Turn on the lock screen. @@ -1981,54 +1974,6 @@ } } -TEST_F(ShelfLayoutManagerTest, GestureRevealsTrayBubble) { - if (!SupportsHostWindowResize()) - return; - - ShelfLayoutManager* shelf = GetShelfLayoutManager(); - shelf->LayoutShelf(); - - // Create a visible window so auto-hide behavior is enforced. - CreateTestWidget(); - - ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow()); - SystemTray* tray = GetSystemTray(); - - // First, make sure the shelf is visible. - shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER); - EXPECT_FALSE(tray->HasSystemBubble()); - - // Now, drag up on the tray to show the bubble. - gfx::Point start = GetShelfWidget()->status_area_widget()-> - GetWindowBoundsInScreen().CenterPoint(); - gfx::Point end(start.x(), start.y() - 100); - generator.GestureScrollSequence(start, end, - base::TimeDelta::FromMilliseconds(10), 1); - EXPECT_TRUE(tray->HasSystemBubble()); - tray->CloseSystemBubble(); - RunAllPendingInMessageLoop(); - EXPECT_FALSE(tray->HasSystemBubble()); - - // Drag again, but only a small amount, and slowly. The bubble should not be - // visible. - end.set_y(start.y() - 30); - generator.GestureScrollSequence(start, end, - base::TimeDelta::FromMilliseconds(500), 100); - EXPECT_FALSE(tray->HasSystemBubble()); - - // Now, hide the shelf. - shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS); - - // Start a drag from the bezel, and drag up to show both the shelf and the - // tray bubble. - start.set_y(start.y() + 100); - end.set_y(start.y() - 400); - generator.GestureScrollSequence(start, end, - base::TimeDelta::FromMilliseconds(10), 1); - EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state()); - EXPECT_TRUE(tray->HasSystemBubble()); -} - TEST_F(ShelfLayoutManagerTest, ShelfFlickerOnTrayActivation) { ShelfLayoutManager* shelf = GetShelfLayoutManager();
diff --git a/ash/system/audio/volume_view.cc b/ash/system/audio/volume_view.cc index b046b35..25f1521 100644 --- a/ash/system/audio/volume_view.cc +++ b/ash/system/audio/volume_view.cc
@@ -10,22 +10,28 @@ #include "ash/system/audio/tray_audio_delegate.h" #include "ash/system/tray/system_tray_item.h" #include "ash/system/tray/tray_constants.h" +#include "ash/system/tray/tray_popup_item_container.h" #include "grit/ash_resources.h" #include "grit/ash_strings.h" #include "ui/base/resource/resource_bundle.h" #include "ui/gfx/canvas.h" #include "ui/gfx/image/image_skia_operations.h" +#include "ui/views/background.h" +#include "ui/views/border.h" #include "ui/views/controls/button/image_button.h" #include "ui/views/controls/image_view.h" +#include "ui/views/controls/separator.h" #include "ui/views/layout/box_layout.h" namespace { const int kVolumeImageWidth = 25; const int kVolumeImageHeight = 25; -const int kBarSeparatorWidth = 25; -const int kBarSeparatorHeight = 30; +const int kSeparatorSize = 3; +const int kSeparatorVerticalInset = 8; const int kSliderRightPaddingToVolumeViewEdge = 17; const int kExtraPaddingBetweenBarAndMore = 10; +const int kExtraPaddingBetweenIconAndSlider = 8; +const int kBoxLayoutPadding = 2; // IDR_AURA_UBER_TRAY_VOLUME_LEVELS contains 5 images, // The one for mute is at the 0 index and the other @@ -67,17 +73,26 @@ SetImage(views::CustomButton::STATE_NORMAL, &image_skia); image_index_ = image_index; } - SchedulePaint(); } private: - // Overridden from views::View. + // views::View: gfx::Size GetPreferredSize() const override { gfx::Size size = views::ToggleImageButton::GetPreferredSize(); size.set_height(kTrayPopupItemHeight); return size; } + // views::CustomButton: + void StateChanged() override { + if (state() == STATE_HOVERED || state() == STATE_PRESSED) { + set_background( + views::Background::CreateSolidBackground(kHoverBackgroundColor)); + } else { + set_background(nullptr); + } + } + system::TrayAudioDelegate* audio_delegate_; gfx::Image image_; int image_index_; @@ -85,52 +100,6 @@ DISALLOW_COPY_AND_ASSIGN(VolumeButton); }; -class VolumeSlider : public views::Slider { - public: - VolumeSlider(views::SliderListener* listener, - system::TrayAudioDelegate* audio_delegate) - : views::Slider(listener, views::Slider::HORIZONTAL), - audio_delegate_(audio_delegate) { - set_focus_border_color(kFocusBorderColor); - SetValue( - static_cast<float>(audio_delegate_->GetOutputVolumeLevel()) / 100.0f); - SetAccessibleName( - ui::ResourceBundle::GetSharedInstance().GetLocalizedString( - IDS_ASH_STATUS_TRAY_VOLUME)); - Update(); - } - ~VolumeSlider() override {} - - void Update() { - UpdateState(!audio_delegate_->IsOutputAudioMuted()); - } - - private: - system::TrayAudioDelegate* audio_delegate_; - - DISALLOW_COPY_AND_ASSIGN(VolumeSlider); -}; - -// Vertical bar separator that can be placed on the VolumeView. -class BarSeparator : public views::View { - public: - BarSeparator() {} - ~BarSeparator() override {} - - // Overriden from views::View. - gfx::Size GetPreferredSize() const override { - return gfx::Size(kBarSeparatorWidth, kBarSeparatorHeight); - } - - private: - void OnPaint(gfx::Canvas* canvas) override { - canvas->FillRect(gfx::Rect(width() / 2, 0, 1, height()), - kButtonStrokeColor); - } - - DISALLOW_COPY_AND_ASSIGN(BarSeparator); -}; - VolumeView::VolumeView(SystemTrayItem* owner, system::TrayAudioDelegate* audio_delegate, bool is_default_view) @@ -138,31 +107,53 @@ audio_delegate_(audio_delegate), icon_(NULL), slider_(NULL), - bar_(NULL), device_type_(NULL), more_(NULL), is_default_view_(is_default_view) { SetFocusable(false); - SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal, - kTrayPopupPaddingHorizontal, 0, kTrayPopupPaddingBetweenItems)); + views::BoxLayout* box_layout = new views::BoxLayout( + views::BoxLayout::kHorizontal, 0, 0, kBoxLayoutPadding); + box_layout->SetDefaultFlex(0); + SetLayoutManager(box_layout); icon_ = new VolumeButton(this, audio_delegate_); + icon_->SetBorder(views::Border::CreateEmptyBorder( + 0, kTrayPopupPaddingHorizontal, 0, kExtraPaddingBetweenIconAndSlider)); AddChildView(icon_); - slider_ = new VolumeSlider(this, audio_delegate_); + slider_ = new views::Slider(this, views::Slider::HORIZONTAL); + slider_->set_focus_border_color(kFocusBorderColor); + slider_->SetValue( + static_cast<float>(audio_delegate_->GetOutputVolumeLevel()) / 100.0f); + slider_->SetAccessibleName( + ui::ResourceBundle::GetSharedInstance().GetLocalizedString( + IDS_ASH_STATUS_TRAY_VOLUME)); + slider_->SetBorder( + views::Border::CreateEmptyBorder(0, 0, 0, kTrayPopupPaddingBetweenItems)); AddChildView(slider_); + box_layout->SetFlexForView(slider_, 1); - bar_ = new BarSeparator; - AddChildView(bar_); + separator_ = new views::Separator(views::Separator::VERTICAL); + separator_->SetColor(kButtonStrokeColor); + separator_->SetPreferredSize(kSeparatorSize); + separator_->SetBorder(views::Border::CreateEmptyBorder( + kSeparatorVerticalInset, 0, kSeparatorVerticalInset, kBoxLayoutPadding)); + + more_region_ = new TrayPopupItemContainer(separator_, true, false); + more_region_->SetBorder( + views::Border::CreateEmptyBorder(0, 0, 0, kTrayPopupPaddingBetweenItems)); + AddChildView(more_region_); device_type_ = new views::ImageView; - AddChildView(device_type_); + more_region_->AddChildView(device_type_); more_ = new views::ImageView; more_->EnableCanvasFlippingForRTLUI(true); more_->SetImage(ui::ResourceBundle::GetSharedInstance().GetImageNamed( IDR_AURA_UBER_TRAY_MORE).ToImageSkia()); - AddChildView(more_); + more_region_->AddChildView(more_); + + set_background(views::Background::CreateSolidBackground(kBackgroundColor)); Update(); } @@ -172,7 +163,7 @@ void VolumeView::Update() { icon_->Update(); - slider_->Update(); + slider_->UpdateState(!audio_delegate_->IsOutputAudioMuted()); UpdateDeviceTypeAndMore(); Layout(); } @@ -196,17 +187,17 @@ } void VolumeView::UpdateDeviceTypeAndMore() { - if (!TrayAudio::ShowAudioDeviceMenu() || !is_default_view_) { - more_->SetVisible(false); - bar_->SetVisible(false); - device_type_->SetVisible(false); + bool show_more = is_default_view_ && TrayAudio::ShowAudioDeviceMenu() && + audio_delegate_->HasAlternativeSources(); + slider_->SetBorder(views::Border::CreateEmptyBorder( + 0, 0, 0, show_more ? kTrayPopupPaddingBetweenItems + : kSliderRightPaddingToVolumeViewEdge)); + + if (!show_more) { + more_region_->SetVisible(false); return; } - bool show_more = audio_delegate_->HasAlternativeSources(); - more_->SetVisible(show_more); - bar_->SetVisible(show_more); - // Show output device icon if necessary. int device_icon = audio_delegate_->GetActiveOutputDeviceIconId(); if (device_icon != system::TrayAudioDelegate::kNoAudioDeviceIcon) { @@ -214,9 +205,15 @@ device_type_->SetImage( ui::ResourceBundle::GetSharedInstance().GetImageNamed( device_icon).ToImageSkia()); + more_region_->SetLayoutManager(new views::BoxLayout( + views::BoxLayout::kHorizontal, 0, 0, kTrayPopupPaddingBetweenItems)); } else { device_type_->SetVisible(false); + more_region_->SetLayoutManager(new views::BoxLayout( + views::BoxLayout::kHorizontal, 0, 0, + kTrayPopupPaddingBetweenItems + kExtraPaddingBetweenBarAndMore)); } + more_region_->SetVisible(true); } void VolumeView::HandleVolumeUp(float level) { @@ -238,54 +235,6 @@ } } -void VolumeView::Layout() { - views::View::Layout(); - - if (!more_->visible()) { - int w = width() - slider_->bounds().x() - - kSliderRightPaddingToVolumeViewEdge; - slider_->SetSize(gfx::Size(w, slider_->height())); - return; - } - - // Make sure the chevron always has the full size. - gfx::Size size = more_->GetPreferredSize(); - gfx::Rect bounds(size); - bounds.set_x(width() - size.width() - kTrayPopupPaddingBetweenItems); - bounds.set_y((height() - size.height()) / 2); - more_->SetBoundsRect(bounds); - - // Layout either bar_ or device_type_ at the left of the more_ button. - views::View* view_left_to_more; - if (device_type_->visible()) - view_left_to_more = device_type_; - else - view_left_to_more = bar_; - gfx::Size view_size = view_left_to_more->GetPreferredSize(); - gfx::Rect view_bounds(view_size); - view_bounds.set_x(more_->bounds().x() - view_size.width() - - kExtraPaddingBetweenBarAndMore); - view_bounds.set_y((height() - view_size.height()) / 2); - view_left_to_more->SetBoundsRect(view_bounds); - - // Layout vertical bar next to view_left_to_more if device_type_ is visible. - if (device_type_->visible()) { - gfx::Size bar_size = bar_->GetPreferredSize(); - gfx::Rect bar_bounds(bar_size); - bar_bounds.set_x(view_left_to_more->bounds().x() - bar_size.width()); - bar_bounds.set_y((height() - bar_size.height()) / 2); - bar_->SetBoundsRect(bar_bounds); - } - - // Layout slider, calculate slider width. - gfx::Rect slider_bounds = slider_->bounds(); - slider_bounds.set_width( - bar_->bounds().x() - - (device_type_->visible() ? 0 : kTrayPopupPaddingBetweenItems) - - slider_bounds.x()); - slider_->SetBoundsRect(slider_bounds); -} - void VolumeView::ButtonPressed(views::Button* sender, const ui::Event& event) { CHECK(sender == icon_); bool mute_on = !audio_delegate_->IsOutputAudioMuted(); @@ -319,11 +268,18 @@ } bool VolumeView::PerformAction(const ui::Event& event) { - if (!more_->visible()) + if (!more_region_->visible()) return false; owner_->TransitionDetailedView(); return true; } +void VolumeView::OnBoundsChanged(const gfx::Rect& previous_bounds) { + // Separator's prefered size is based on set bounds. When an empty bounds is + // set on first layout this causes BoxLayout to ignore the separator. Reset + // its height on each bounds change so that it is laid out properly. + separator_->SetSize(gfx::Size(kSeparatorSize, bounds().height())); +} + } // namespace tray } // namespace ash
diff --git a/ash/system/audio/volume_view.h b/ash/system/audio/volume_view.h index c770277..6db6789 100644 --- a/ash/system/audio/volume_view.h +++ b/ash/system/audio/volume_view.h
@@ -13,10 +13,11 @@ namespace views { class View; class ImageView; +class Separator; +class Slider; } namespace ash { -class HoverHighlightView; class SystemTrayItem; namespace system { @@ -24,9 +25,7 @@ } namespace tray { -class BarSeparator; class VolumeButton; -class VolumeSlider; class VolumeView : public ActionableView, public views::ButtonListener, @@ -49,9 +48,6 @@ void HandleVolumeUp(float percent); void HandleVolumeDown(float percent); - // Overridden from views::View. - void Layout() override; - // Overridden from views::ButtonListener. void ButtonPressed(views::Button* sender, const ui::Event& event) override; @@ -64,11 +60,15 @@ // Overriden from ActionableView. bool PerformAction(const ui::Event& event) override; + // views::View: + void OnBoundsChanged(const gfx::Rect& previous_bounds) override; + SystemTrayItem* owner_; system::TrayAudioDelegate* audio_delegate_; + views::View* more_region_; VolumeButton* icon_; - VolumeSlider* slider_; - BarSeparator* bar_; + views::Slider* slider_; + views::Separator* separator_; views::ImageView* device_type_; views::ImageView* more_; bool is_default_view_;
diff --git a/ash/system/date/date_default_view.cc b/ash/system/date/date_default_view.cc index aa86cc8f..ca64a1ef 100644 --- a/ash/system/date/date_default_view.cc +++ b/ash/system/date/date_default_view.cc
@@ -102,6 +102,10 @@ return help_button_; } +const views::View* DateDefaultView::GetShutdownButtonViewForTest() const { + return shutdown_button_; +} + tray::DateView* DateDefaultView::GetDateView() { return date_view_; }
diff --git a/ash/system/date/date_default_view.h b/ash/system/date/date_default_view.h index 25bddfca..2efcdf8 100644 --- a/ash/system/date/date_default_view.h +++ b/ash/system/date/date_default_view.h
@@ -29,6 +29,7 @@ ~DateDefaultView() override; views::View* GetHelpButtonView(); + const views::View* GetShutdownButtonViewForTest() const; tray::DateView* GetDateView(); const tray::DateView* GetDateView() const;
diff --git a/ash/test/test_metro_viewer_process_host.cc b/ash/test/test_metro_viewer_process_host.cc index 00c00d25..04fbaa5 100644 --- a/ash/test/test_metro_viewer_process_host.cc +++ b/ash/test/test_metro_viewer_process_host.cc
@@ -7,6 +7,7 @@ #include <windef.h> #include "base/logging.h" +#include "base/process/process.h" #include "ui/aura/remote_window_tree_host_win.h" #include "ui/gfx/win/dpi.h" @@ -24,15 +25,13 @@ void TestMetroViewerProcessHost::TerminateViewer() { base::ProcessId viewer_process_id = GetViewerProcessId(); if (viewer_process_id != base::kNullProcessId) { - base::ProcessHandle viewer_process = NULL; - base::OpenProcessHandleWithAccess( + base::Process viewer_process = base::Process::OpenWithAccess( viewer_process_id, - PROCESS_QUERY_INFORMATION | SYNCHRONIZE | PROCESS_TERMINATE, - &viewer_process); - if (viewer_process) { - ::TerminateProcess(viewer_process, 0); - ::WaitForSingleObject(viewer_process, INFINITE); - ::CloseHandle(viewer_process); + PROCESS_QUERY_INFORMATION | SYNCHRONIZE | PROCESS_TERMINATE); + if (viewer_process.IsValid()) { + viewer_process.Terminate(0); + int exit_code; + viewer_process.WaitForExit(&exit_code); } } }
diff --git a/ash/wm/gestures/shelf_gesture_handler.cc b/ash/wm/gestures/shelf_gesture_handler.cc index 6d4a01a..eb485ad 100644 --- a/ash/wm/gestures/shelf_gesture_handler.cc +++ b/ash/wm/gestures/shelf_gesture_handler.cc
@@ -11,7 +11,6 @@ #include "ash/shelf/shelf_widget.h" #include "ash/shell.h" #include "ash/system/status_area_widget.h" -#include "ash/wm/gestures/tray_gesture_handler.h" #include "ash/wm/window_state.h" #include "ash/wm/window_util.h" #include "ui/aura/window.h" @@ -63,14 +62,7 @@ return false; if (event.type() == ui::ET_GESTURE_SCROLL_UPDATE) { - if (tray_handler_) { - if (!tray_handler_->UpdateGestureDrag(event)) - tray_handler_.reset(); - } else if (shelf->UpdateGestureDrag(event) == - ShelfLayoutManager::DRAG_TRAY) { - tray_handler_.reset(new TrayGestureHandler()); - } - + shelf->UpdateGestureDrag(event); return true; } @@ -78,11 +70,6 @@ if (event.type() == ui::ET_GESTURE_SCROLL_END || event.type() == ui::ET_SCROLL_FLING_START) { - if (tray_handler_) { - tray_handler_->CompleteGestureDrag(event); - tray_handler_.reset(); - } - shelf->CompleteGestureDrag(event); return true; }
diff --git a/ash/wm/gestures/shelf_gesture_handler.h b/ash/wm/gestures/shelf_gesture_handler.h index 974bf2b..c7211db 100644 --- a/ash/wm/gestures/shelf_gesture_handler.h +++ b/ash/wm/gestures/shelf_gesture_handler.h
@@ -13,7 +13,6 @@ } namespace ash { -class TrayGestureHandler; // This manages gestures on the shelf (e.g. launcher, status tray) that affects // the shelf visibility. @@ -30,8 +29,6 @@ private: bool drag_in_progress_; - scoped_ptr<TrayGestureHandler> tray_handler_; - DISALLOW_COPY_AND_ASSIGN(ShelfGestureHandler); };
diff --git a/ash/wm/gestures/tray_gesture_handler.cc b/ash/wm/gestures/tray_gesture_handler.cc deleted file mode 100644 index ac72929..0000000 --- a/ash/wm/gestures/tray_gesture_handler.cc +++ /dev/null
@@ -1,107 +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 "ash/wm/gestures/tray_gesture_handler.h" - -#include "ash/shell.h" -#include "ash/system/tray/system_tray.h" -#include "ash/system/tray/system_tray_bubble.h" -#include "ui/aura/window.h" -#include "ui/compositor/layer.h" -#include "ui/events/event.h" -#include "ui/gfx/transform.h" -#include "ui/views/widget/widget.h" - -const int kMinBubbleHeight = 13; - -namespace ash { - -TrayGestureHandler::TrayGestureHandler() - : widget_(NULL), - gesture_drag_amount_(0) { - // TODO(oshima): Support multiple display case. - SystemTray* tray = Shell::GetInstance()->GetPrimarySystemTray(); - tray->ShowDefaultView(BUBBLE_CREATE_NEW); - SystemTrayBubble* bubble = tray->GetSystemBubble(); - if (!bubble) - return; - bubble->bubble_view()->set_gesture_dragging(true); - widget_ = bubble->bubble_view()->GetWidget(); - widget_->AddObserver(this); - - gfx::Rect bounds = widget_->GetWindowBoundsInScreen(); - int height_change = bounds.height() - kMinBubbleHeight; - bounds.set_height(kMinBubbleHeight); - bounds.set_y(bounds.y() + height_change); - widget_->SetBounds(bounds); -} - -TrayGestureHandler::~TrayGestureHandler() { - if (widget_) - widget_->RemoveObserver(this); -} - -bool TrayGestureHandler::UpdateGestureDrag(const ui::GestureEvent& event) { - CHECK_EQ(ui::ET_GESTURE_SCROLL_UPDATE, event.type()); - if (!widget_) - return false; - - gesture_drag_amount_ += event.details().scroll_y(); - if (gesture_drag_amount_ > 0 && gesture_drag_amount_ < kMinBubbleHeight) { - widget_->Close(); - return false; - } - - gfx::Rect bounds = widget_->GetWindowBoundsInScreen(); - int new_height = std::min( - kMinBubbleHeight + std::max(0, static_cast<int>(-gesture_drag_amount_)), - widget_->GetContentsView()->GetPreferredSize().height()); - int height_change = bounds.height() - new_height; - bounds.set_height(new_height); - bounds.set_y(bounds.y() + height_change); - widget_->SetBounds(bounds); - return true; -} - -void TrayGestureHandler::CompleteGestureDrag(const ui::GestureEvent& event) { - if (!widget_) - return; - - widget_->RemoveObserver(this); - - // Close the widget if it hasn't been dragged enough. - bool should_close = false; - int height = widget_->GetWindowBoundsInScreen().height(); - int preferred_height = - widget_->GetContentsView()->GetPreferredSize().height(); - if (event.type() == ui::ET_GESTURE_SCROLL_END) { - const float kMinThresholdGestureDrag = 0.4f; - if (height < preferred_height * kMinThresholdGestureDrag) - should_close = true; - } else if (event.type() == ui::ET_SCROLL_FLING_START) { - const float kMinThresholdGestureDragExposeFling = 0.25f; - const float kMinThresholdGestureFling = 1000.f; - if (height < preferred_height * kMinThresholdGestureDragExposeFling && - event.details().velocity_y() > -kMinThresholdGestureFling) - should_close = true; - } else { - NOTREACHED(); - } - - if (should_close) { - widget_->Close(); - } else { - SystemTrayBubble* bubble = - Shell::GetInstance()->GetPrimarySystemTray()->GetSystemBubble(); - if (bubble) - bubble->bubble_view()->set_gesture_dragging(false); - } -} - -void TrayGestureHandler::OnWidgetDestroying(views::Widget* widget) { - CHECK_EQ(widget_, widget); - widget_ = NULL; -} - -} // namespace ash
diff --git a/ash/wm/gestures/tray_gesture_handler.h b/ash/wm/gestures/tray_gesture_handler.h deleted file mode 100644 index 529349868..0000000 --- a/ash/wm/gestures/tray_gesture_handler.h +++ /dev/null
@@ -1,46 +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 ASH_WM_GESTURES_TRAY_GESTURE_HANDLER_H_ -#define ASH_WM_GESTURES_TRAY_GESTURE_HANDLER_H_ - -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "ui/views/widget/widget_observer.h" - -namespace ui { -class GestureEvent; -} - -namespace ash { - -// Handles gesture events on the shelf to show the system tray bubble. -class TrayGestureHandler : public views::WidgetObserver { - public: - TrayGestureHandler(); - ~TrayGestureHandler() override; - - // Handles a gesture-update event and updates the dragging state of the tray - // bubble. Returns true if the handler can continue to process gesture events - // for the bubble. Returns false if it should no longer receive gesture - // events. - bool UpdateGestureDrag(const ui::GestureEvent& event); - - void CompleteGestureDrag(const ui::GestureEvent& event); - - private: - void OnWidgetDestroying(views::Widget* widget) override; - - // The widget for the tray-bubble. - views::Widget* widget_; - - // The amount that has been dragged. - float gesture_drag_amount_; - - DISALLOW_COPY_AND_ASSIGN(TrayGestureHandler); -}; - -} // namespace ash - -#endif // ASH_WM_GESTURES_TRAY_GESTURE_HANDLER_H_
diff --git a/ash/wm/overview/overview_window_button.cc b/ash/wm/overview/overview_window_button.cc new file mode 100644 index 0000000..2fa3248 --- /dev/null +++ b/ash/wm/overview/overview_window_button.cc
@@ -0,0 +1,155 @@ +// Copyright 2015 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/screen_util.h" +#include "ash/shell.h" +#include "ash/shell_window_ids.h" +#include "ash/wm/overview/overview_animation_type.h" +#include "ash/wm/overview/overview_window_button.h" +#include "ash/wm/overview/overview_window_targeter.h" +#include "ash/wm/overview/scoped_overview_animation_settings.h" +#include "ash/wm/window_state.h" +#include "ui/aura/scoped_window_targeter.h" +#include "ui/aura/window.h" +#include "ui/base/resource/resource_bundle.h" +#include "ui/views/border.h" +#include "ui/views/controls/button/label_button.h" +#include "ui/views/widget/widget.h" + +namespace ash { + +namespace { + +// Foreground label color. +static const SkColor kLabelColor = SK_ColorWHITE; + +// Label shadow color. +static const SkColor kLabelShadow = 0xB0000000; + +// Solid shadow length from the label +static const int kVerticalShadowOffset = 1; + +// Amount of blur applied to the label shadow +static const int kShadowBlur = 10; + +} // namespace + +// LabelButton shown under each of the windows. +class OverviewWindowButton::OverviewButtonView : public views::LabelButton { + public: + OverviewButtonView(views::ButtonListener* listener, + const base::string16& text) + : views::LabelButton(listener, text), + selector_item_bounds_(gfx::Rect()) {} + + ~OverviewButtonView() override {} + + // Updates the |selector_item_bounds_|, converting them to our coordinates. + void SetSelectorItemBounds(const gfx::Rect& selector_item_bounds) { + selector_item_bounds_ = ScreenUtil::ConvertRectFromScreen( + GetWidget()->GetNativeWindow()->GetRootWindow(), selector_item_bounds); + gfx::Point origin = selector_item_bounds_.origin(); + gfx::Rect target_bounds = GetWidget()->GetNativeWindow()->GetTargetBounds(); + origin.Offset(-target_bounds.x(), -target_bounds.y()); + selector_item_bounds_.set_origin(origin); + } + + // views::View: + void OnMouseReleased(const ui::MouseEvent& event) override { + if (!selector_item_bounds_.Contains(event.location())) + return; + + NotifyClick(event); + } + + private: + // Bounds to check if a mouse release occurred outside the window item. + gfx::Rect selector_item_bounds_; + + DISALLOW_COPY_AND_ASSIGN(OverviewButtonView); +}; + +OverviewWindowButton::OverviewWindowButton(aura::Window* target) + : target_(target), window_label_(new views::Widget) { + views::Widget::InitParams params; + params.type = views::Widget::InitParams::TYPE_POPUP; + params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; + params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; + params.parent = Shell::GetContainer(target_->GetRootWindow(), + kShellWindowId_OverlayContainer); + params.visible_on_all_workspaces = true; + window_label_->set_focus_on_creation(false); + window_label_->Init(params); + window_label_button_view_ = new OverviewButtonView(this, target_->title()); + window_label_button_view_->SetTextColor(views::LabelButton::STATE_NORMAL, + kLabelColor); + window_label_button_view_->SetTextColor(views::LabelButton::STATE_HOVERED, + kLabelColor); + window_label_button_view_->SetTextColor(views::LabelButton::STATE_PRESSED, + kLabelColor); + window_label_button_view_->set_animate_on_state_change(false); + window_label_button_view_->SetHorizontalAlignment(gfx::ALIGN_CENTER); + window_label_button_view_->SetBorder(views::Border::NullBorder()); + window_label_button_view_->SetTextShadows(gfx::ShadowValues( + 1, gfx::ShadowValue(gfx::Point(0, kVerticalShadowOffset), kShadowBlur, + kLabelShadow))); + ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); + window_label_button_view_->SetFontList( + bundle.GetFontList(ui::ResourceBundle::BoldFont)); + window_label_->SetContentsView(window_label_button_view_); + + overview_window_targeter_ = + new OverviewWindowTargeter(window_label_->GetNativeWindow()); + scoped_window_targeter_.reset(new aura::ScopedWindowTargeter( + target, scoped_ptr<OverviewWindowTargeter>(overview_window_targeter_))); +} + +OverviewWindowButton::~OverviewWindowButton() { +} + +void OverviewWindowButton::SetBounds( + const gfx::Rect& bounds, + const OverviewAnimationType& animation_type) { + if (!window_label_->IsVisible()) { + window_label_->Show(); + ScopedOverviewAnimationSettings::SetupFadeInAfterLayout( + window_label_->GetNativeWindow()); + } + gfx::Rect converted_bounds = + ScreenUtil::ConvertRectFromScreen(target_->GetRootWindow(), bounds); + gfx::Rect label_bounds(converted_bounds.x(), converted_bounds.bottom(), + converted_bounds.width(), 0); + label_bounds.set_height( + window_label_->GetContentsView()->GetPreferredSize().height()); + label_bounds.set_y( + label_bounds.y() - + window_label_->GetContentsView()->GetPreferredSize().height()); + + ScopedOverviewAnimationSettings animation_settings( + animation_type, window_label_->GetNativeWindow()); + + window_label_->GetNativeWindow()->SetBounds(label_bounds); + window_label_button_view_->SetSelectorItemBounds(bounds); + overview_window_targeter_->set_bounds( + ScreenUtil::ConvertRectFromScreen(target_->GetRootWindow(), bounds)); +} + +void OverviewWindowButton::SendFocusAlert() const { + window_label_button_view_->NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, true); +} + +void OverviewWindowButton::SetLabelText(const base::string16& title) { + window_label_button_view_->SetText(title); +} + +void OverviewWindowButton::SetOpacity(float opacity) { + window_label_->GetNativeWindow()->layer()->SetOpacity(opacity); +} + +void OverviewWindowButton::ButtonPressed(views::Button* sender, + const ui::Event& event) { + wm::GetWindowState(target_)->Activate(); +} + +} // namespace ash
diff --git a/ash/wm/overview/overview_window_button.h b/ash/wm/overview/overview_window_button.h new file mode 100644 index 0000000..f3e18122 --- /dev/null +++ b/ash/wm/overview/overview_window_button.h
@@ -0,0 +1,71 @@ +// Copyright 2015 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_WM_OVERVIEW_OVERVIEW_WINDOW_BUTTON_H_ +#define ASH_WM_OVERVIEW_OVERVIEW_WINDOW_BUTTON_H_ + +#include "ash/wm/overview/scoped_transform_overview_window.h" +#include "ui/views/controls/button/button.h" + +namespace aura { +class ScopedWindowTargeter; +} + +namespace ash { + +class OverviewWindowTargeter; + +// A class that encapsulates the LabelButton and targeting logic for overview +// mode. +class OverviewWindowButton : public views::ButtonListener { + public: + // |target| is the window that should be activated when the button is pressed. + explicit OverviewWindowButton(aura::Window* target); + + ~OverviewWindowButton() override; + + // Sets the label and targetable bounds. + void SetBounds(const gfx::Rect& bounds, + const OverviewAnimationType& animation_type); + + // Sends an a11y focus alert so that, if chromevox is enabled, the window + // label is read. + void SendFocusAlert() const; + + // Sets the label text. + void SetLabelText(const base::string16& title); + + // Sets the label opacity. + void SetOpacity(float opacity); + + // views::ButtonListener + void ButtonPressed(views::Button* sender, const ui::Event& event) override; + + private: + friend class WindowSelectorTest; + + // LabelButton shown under each of the windows. + class OverviewButtonView; + + // Window that the button will activate on click. + aura::Window* target_; + + // Label under the window displaying its active tab name. + scoped_ptr<views::Widget> window_label_; + + // View for the label button under the window. + OverviewButtonView* window_label_button_view_; + + // Reference to the targeter implemented by the scoped window targeter. + OverviewWindowTargeter* overview_window_targeter_; + + // Stores and restores on exit the actual window targeter. + scoped_ptr<aura::ScopedWindowTargeter> scoped_window_targeter_; + + DISALLOW_COPY_AND_ASSIGN(OverviewWindowButton); +}; + +} // namespace ash + +#endif // ASH_WM_OVERVIEW_OVERVIEW_WINDOW_BUTTON_H_
diff --git a/ash/wm/overview/overview_window_targeter.cc b/ash/wm/overview/overview_window_targeter.cc new file mode 100644 index 0000000..0fa04ce --- /dev/null +++ b/ash/wm/overview/overview_window_targeter.cc
@@ -0,0 +1,32 @@ +// Copyright 2015 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/wm/overview/overview_window_targeter.h" +#include "ui/aura/window.h" + +namespace ash { + +OverviewWindowTargeter::OverviewWindowTargeter(aura::Window* target) + : bounds_(gfx::Rect()), target_(target) { +} + +OverviewWindowTargeter::~OverviewWindowTargeter() { +} + +ui::EventTarget* OverviewWindowTargeter::FindTargetForLocatedEvent( + ui::EventTarget* target, + ui::LocatedEvent* event) { + // Manually override the location of the event to make sure it targets the + // contents view on the target window. + event->set_location(gfx::PointF(0, 0)); + return target_; +} + +bool OverviewWindowTargeter::EventLocationInsideBounds( + ui::EventTarget* target, + const ui::LocatedEvent& event) const { + return bounds_.Contains(event.location()); +} + +} // namespace ash
diff --git a/ash/wm/overview/overview_window_targeter.h b/ash/wm/overview/overview_window_targeter.h new file mode 100644 index 0000000..e60017c --- /dev/null +++ b/ash/wm/overview/overview_window_targeter.h
@@ -0,0 +1,45 @@ +// Copyright 2015 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_WM_OVERVIEW_OVERVIEW_WINDOW_TARGETER_H_ +#define ASH_WM_OVERVIEW_OVERVIEW_WINDOW_TARGETER_H_ + +#include "ui/aura/window_targeter.h" +#include "ui/gfx/geometry/rect.h" + +namespace ash { + +// A targeter for the windows in the overview. Avoids propagating events to +// window children and uses the WindowSelectorItem bounds to check for hits. +class OverviewWindowTargeter : public aura::WindowTargeter { + public: + explicit OverviewWindowTargeter(aura::Window* target); + + ~OverviewWindowTargeter() override; + + // Sets the targetable bounds. + void set_bounds(const gfx::Rect& bounds) { bounds_ = bounds; } + + // ui::EventTargeter: + ui::EventTarget* FindTargetForLocatedEvent(ui::EventTarget* target, + ui::LocatedEvent* event) override; + + protected: + // ui::EventTargeter: + bool EventLocationInsideBounds(ui::EventTarget* target, + const ui::LocatedEvent& event) const override; + + private: + // Bounds used to check for event hits in the root window coordinates. + gfx::Rect bounds_; + + // Target to which events are redirected. + aura::Window* target_; + + DISALLOW_COPY_AND_ASSIGN(OverviewWindowTargeter); +}; + +} // namespace ash + +#endif // ASH_WM_OVERVIEW_OVERVIEW_WINDOW_TARGETER_H_
diff --git a/ash/wm/overview/scoped_overview_animation_settings.cc b/ash/wm/overview/scoped_overview_animation_settings.cc index e0cf977..9dc172d2 100644 --- a/ash/wm/overview/scoped_overview_animation_settings.cc +++ b/ash/wm/overview/scoped_overview_animation_settings.cc
@@ -73,4 +73,15 @@ ScopedOverviewAnimationSettings::~ScopedOverviewAnimationSettings() { } +// static: +void ScopedOverviewAnimationSettings::SetupFadeInAfterLayout( + aura::Window* window) { + ui::Layer* layer = window->layer(); + layer->SetOpacity(0.0f); + ScopedOverviewAnimationSettings animation_settings( + OverviewAnimationType::OVERVIEW_ANIMATION_ENTER_OVERVIEW_MODE_FADE_IN, + window); + layer->SetOpacity(1.0f); +} + } // namespace ash
diff --git a/ash/wm/overview/scoped_overview_animation_settings.h b/ash/wm/overview/scoped_overview_animation_settings.h index a558c7e..4ea09e5 100644 --- a/ash/wm/overview/scoped_overview_animation_settings.h +++ b/ash/wm/overview/scoped_overview_animation_settings.h
@@ -24,6 +24,11 @@ aura::Window* window); virtual ~ScopedOverviewAnimationSettings(); + // Convenvience method to fade in a Window with predefined animation settings. + // Note: The fade in animation will occur after a delay where the delay is how + // long the lay out animations take. + static void SetupFadeInAfterLayout(aura::Window* window); + private: // The managed animation settings. ui::ScopedLayerAnimationSettings animation_settings_;
diff --git a/ash/wm/overview/scoped_transform_overview_window.cc b/ash/wm/overview/scoped_transform_overview_window.cc index 5d2734d..a3ebe83 100644 --- a/ash/wm/overview/scoped_transform_overview_window.cc +++ b/ash/wm/overview/scoped_transform_overview_window.cc
@@ -166,8 +166,6 @@ ScopedTransformOverviewWindow::ScopedTransformOverviewWindow( aura::Window* window) : window_(window), - activate_button_(new TransparentActivateWindowButton( - window_->GetRootWindow(), this)), minimized_(window->GetProperty(aura::client::kShowStateKey) == ui::SHOW_STATE_MINIMIZED), ignored_by_shelf_(wm::GetWindowState(window)->ignored_by_shelf()), @@ -304,10 +302,6 @@ } } -void ScopedTransformOverviewWindow::Select() { - wm::GetWindowState(window_)->Activate(); -} - void ScopedTransformOverviewWindow::Close() { aura::Window* window = GetTransientRoot(window_); views::Widget::GetWidgetForNativeView(window)->Close();
diff --git a/ash/wm/overview/scoped_transform_overview_window.h b/ash/wm/overview/scoped_transform_overview_window.h index 99ad6589..8a2dec7f 100644 --- a/ash/wm/overview/scoped_transform_overview_window.h +++ b/ash/wm/overview/scoped_transform_overview_window.h
@@ -6,8 +6,6 @@ #define ASH_WM_OVERVIEW_SCOPED_TRANSFORM_OVERVIEW_WINDOW_H_ #include "ash/wm/overview/scoped_overview_animation_settings.h" -#include "ash/wm/overview/transparent_activate_window_button.h" -#include "ash/wm/overview/transparent_activate_window_button_delegate.h" #include "base/compiler_specific.h" #include "base/memory/scoped_ptr.h" #include "base/memory/scoped_vector.h" @@ -35,8 +33,7 @@ // class allows transforming the windows with a helper to determine the best // fit in certain bounds. The window's state is restored on destruction of this // object. -class ScopedTransformOverviewWindow - : public TransparentActivateWindowButtonDelegate { +class ScopedTransformOverviewWindow { public: typedef ScopedVector<ScopedOverviewAnimationSettings> ScopedAnimationSettings; @@ -51,7 +48,7 @@ const gfx::Rect& dst_rect); explicit ScopedTransformOverviewWindow(aura::Window* window); - ~ScopedTransformOverviewWindow() override; + ~ScopedTransformOverviewWindow(); gfx::Transform get_overview_transform() const { return overview_transform_; } @@ -59,10 +56,6 @@ overview_transform_ = transform; } - TransparentActivateWindowButton* activate_button() { - return activate_button_.get(); - } - // Starts an animation sequence which will use animation settings specified by // |animation_type|. The |animation_settings| container is populated with // scoped entities and the container should be destroyed at the end of the @@ -115,9 +108,6 @@ // Closes the transient root of the window managed by |this|. void Close(); - // ash::TransparentActivateWindowButtonDelegate: - void Select() override; - private: // Shows the window if it was minimized. void ShowWindowIfMinimized(); @@ -125,9 +115,6 @@ // A weak pointer to the real window in the overview. aura::Window* window_; - // The transparent overlay that captures events. - scoped_ptr<TransparentActivateWindowButton> activate_button_; - // If true, the window was minimized and should be restored if the window // was not selected. bool minimized_;
diff --git a/ash/wm/overview/transparent_activate_window_button.cc b/ash/wm/overview/transparent_activate_window_button.cc deleted file mode 100644 index 4189bf1..0000000 --- a/ash/wm/overview/transparent_activate_window_button.cc +++ /dev/null
@@ -1,136 +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 "ash/wm/overview/transparent_activate_window_button.h" - -#include <vector> - -#include "ash/shell.h" -#include "ash/shell_window_ids.h" -#include "ash/wm/overview/transparent_activate_window_button_delegate.h" -#include "ui/events/event.h" -#include "ui/events/gesture_event_details.h" -#include "ui/gfx/display.h" -#include "ui/gfx/screen.h" -#include "ui/views/controls/button/button.h" -#include "ui/views/controls/button/custom_button.h" -#include "ui/views/widget/widget.h" - -namespace ash { - -namespace { -const char kTransparentButtonName[] = "TransparentButton"; - -// Transparent button that handles events to activate or close windows in -// overview mode. -class TransparentButton - : public views::CustomButton, - public views::ButtonListener { - public: - explicit TransparentButton(TransparentActivateWindowButtonDelegate* delegate); - - ~TransparentButton() override; - - TransparentActivateWindowButtonDelegate* delegate() { return delegate_; } - - // views::View: - void OnGestureEvent(ui::GestureEvent* event) override; - - const char* GetClassName() const override { return kTransparentButtonName; } - - // views::ButtonListener: - void ButtonPressed(views::Button* sender, const ui::Event& event) override; - - private: - TransparentActivateWindowButtonDelegate* delegate_; - - DISALLOW_COPY_AND_ASSIGN(TransparentButton); -}; - -TransparentButton::TransparentButton( - TransparentActivateWindowButtonDelegate* delegate) - : CustomButton(this), - delegate_(delegate) { -} - -TransparentButton::~TransparentButton() { -} - -void TransparentButton::OnGestureEvent(ui::GestureEvent* event) { - // TODO(tdanderson): Re-evaluate whether we want to set capture once - // the a fix has landed to avoid crashing when a window - // having an active gesture sequence is destroyed as a - // result of a gesture in a separate window. Consider using - // a StaticWindowTargeter instead of a transparent overlay - // widget to re-direct input events. - if (event->type() == ui::ET_GESTURE_TAP_DOWN) - GetWidget()->SetCapture(this); - - if (event->type() == ui::ET_GESTURE_TAP || - event->type() == ui::ET_GESTURE_END) { - GetWidget()->ReleaseCapture(); - } - - CustomButton::OnGestureEvent(event); - event->StopPropagation(); -} - -void TransparentButton::ButtonPressed(views::Button* sender, - const ui::Event& event) { - delegate_->Select(); -} - -// Initializes the event handler transparent window. -views::Widget* InitEventHandler(aura::Window* root_window) { - views::Widget* widget = new views::Widget; - views::Widget::InitParams params; - params.type = views::Widget::InitParams::TYPE_POPUP; - params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; - params.accept_events = true; - params.parent = Shell::GetContainer(root_window, - kShellWindowId_OverlayContainer); - widget->set_focus_on_creation(false); - widget->Init(params); - widget->Show(); - - aura::Window* handler = widget->GetNativeWindow(); - handler->parent()->StackChildAtBottom(handler); - - return widget; -} - -} // namespace - -TransparentActivateWindowButton::TransparentActivateWindowButton( - aura::Window* root_window, - TransparentActivateWindowButtonDelegate* delegate) - : event_handler_widget_(InitEventHandler(root_window)), - transparent_button_(new TransparentButton(delegate)) { - event_handler_widget_->SetContentsView(transparent_button_); -} - -TransparentActivateWindowButton::~TransparentActivateWindowButton() { -} - -void TransparentActivateWindowButton::SetAccessibleName( - const base::string16& name) { - transparent_button_->SetAccessibleName(name); -} - -void TransparentActivateWindowButton::SetBounds(const gfx::Rect& bounds) { - aura::Window* window = event_handler_widget_->GetNativeWindow(); - const gfx::Display& display = gfx::Screen::GetScreenFor( - window)->GetDisplayNearestWindow(window); - // Explicitly specify the display so that the window doesn't change root - // windows and cause the z-order of the transparent overlays to be updated. - window->SetBoundsInScreen(bounds, display); -} - -void TransparentActivateWindowButton::SendFocusAlert() const { - event_handler_widget_->GetContentsView()-> - NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, true); -} - -} // namespace ash
diff --git a/ash/wm/overview/transparent_activate_window_button.h b/ash/wm/overview/transparent_activate_window_button.h deleted file mode 100644 index 9dac693..0000000 --- a/ash/wm/overview/transparent_activate_window_button.h +++ /dev/null
@@ -1,57 +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 ASH_WM_OVERVIEW_TRANSPARENT_ACTIVATE_WINDOW_BUTTON_H_ -#define ASH_WM_OVERVIEW_TRANSPARENT_ACTIVATE_WINDOW_BUTTON_H_ - -#include "base/macros.h" -#include "base/memory/scoped_ptr.h" -#include "base/strings/string16.h" -#include "ui/gfx/geometry/rect.h" - -namespace aura { -class Window; -} // namespace aura - -namespace views { -class Button; -class Widget; -} // namespace views - -namespace ash { - -class TransparentActivateWindowButtonDelegate; - -// Transparent window that covers window selector items and handles mouse and -// gestures on overview mode for them. -class TransparentActivateWindowButton { - public: - TransparentActivateWindowButton( - aura::Window* root_window, - TransparentActivateWindowButtonDelegate* delegate); - ~TransparentActivateWindowButton(); - - // Sets the accessibility name. - void SetAccessibleName(const base::string16& name); - - // Sets the bounds of the transparent window. - void SetBounds(const gfx::Rect& bounds); - - // Sends an accessibility focus alert so that if chromevox is enabled, the - // window title is read. - void SendFocusAlert() const; - - private: - // The transparent window event handler widget itself. - scoped_ptr<views::Widget> event_handler_widget_; - - // The transparent button view that handles user input. Not owned. - views::Button* transparent_button_; - - DISALLOW_COPY_AND_ASSIGN(TransparentActivateWindowButton); -}; - -} // namespace ash - -#endif // ASH_WM_OVERVIEW_TRANSPARENT_ACTIVATE_WINDOW_BUTTON_H_
diff --git a/ash/wm/overview/transparent_activate_window_button_delegate.h b/ash/wm/overview/transparent_activate_window_button_delegate.h deleted file mode 100644 index 07695f0..0000000 --- a/ash/wm/overview/transparent_activate_window_button_delegate.h +++ /dev/null
@@ -1,30 +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. -// A delegate that - -#ifndef ASH_WM_OVERVIEW_TRANSPARENT_ACTIVATE_WINDOW_BUTTON_DELEGATE_H_ -#define ASH_WM_OVERVIEW_TRANSPARENT_ACTIVATE_WINDOW_BUTTON_DELEGATE_H_ - -#include "ash/ash_export.h" - -namespace ash { - -// A pure-virtual delegate that is used by the TransparentActivateWindowButton -// to manipulate windows while in overview mode. -class ASH_EXPORT TransparentActivateWindowButtonDelegate { - public: - // Called when the TransparentActivateWindowButton was selected. - virtual void Select() = 0; - - protected: - TransparentActivateWindowButtonDelegate() {} - virtual ~TransparentActivateWindowButtonDelegate() {} - - private: - DISALLOW_COPY_AND_ASSIGN(TransparentActivateWindowButtonDelegate); -}; - -} // namespace ash - -#endif // ASH_WM_OVERVIEW_TRANSPARENT_ACTIVATE_WINDOW_BUTTON_DELEGATE_H_
diff --git a/ash/wm/overview/window_selector_item.cc b/ash/wm/overview/window_selector_item.cc index 4ab47e9..d57f0adb 100644 --- a/ash/wm/overview/window_selector_item.cc +++ b/ash/wm/overview/window_selector_item.cc
@@ -11,10 +11,10 @@ #include "ash/shell.h" #include "ash/shell_window_ids.h" #include "ash/wm/overview/overview_animation_type.h" +#include "ash/wm/overview/overview_window_button.h" #include "ash/wm/overview/scoped_overview_animation_settings.h" #include "ash/wm/overview/scoped_transform_overview_window.h" #include "ash/wm/overview/window_selector_controller.h" -#include "ash/wm/window_state.h" #include "base/auto_reset.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" @@ -28,7 +28,6 @@ #include "ui/gfx/transform_util.h" #include "ui/strings/grit/ui_strings.h" #include "ui/views/controls/button/image_button.h" -#include "ui/views/controls/label.h" #include "ui/views/layout/box_layout.h" #include "ui/views/widget/widget.h" #include "ui/wm/core/window_util.h" @@ -42,24 +41,6 @@ // closest distance between adjacent windows will be twice this amount. static const int kWindowMargin = 30; -// Foreground label color. -static const SkColor kLabelColor = SK_ColorWHITE; - -// Background label color. -static const SkColor kLabelBackground = SK_ColorTRANSPARENT; - -// Label shadow color. -static const SkColor kLabelShadow = 0xB0000000; - -// Vertical padding for the label, both over and beneath it. -static const int kVerticalLabelPadding = 20; - -// Solid shadow length from the label -static const int kVerticalShadowOffset = 1; - -// Amount of blur applied to the label shadow -static const int kShadowBlur = 10; - // Opacity for dimmed items. static const float kDimmedItemOpacity = 0.5f; @@ -75,18 +56,6 @@ return ToEnclosingRect(bounds); } -// Convenvience method to fade in a Window with predefined animation settings. -// Note: The fade in animation will occur after a delay where the delay is how -// long the lay out animations take. -void SetupFadeInAfterLayout(aura::Window* window) { - ui::Layer* layer = window->layer(); - layer->SetOpacity(0.0f); - ScopedOverviewAnimationSettings animation_settings( - OverviewAnimationType::OVERVIEW_ANIMATION_ENTER_OVERVIEW_MODE_FADE_IN, - window); - layer->SetOpacity(1.0f); -} - // An image button with a close window icon. class OverviewCloseButton : public views::ImageButton { public: @@ -118,10 +87,8 @@ root_window_(window->GetRootWindow()), transform_window_(window), in_bounds_update_(false), - window_label_view_(nullptr), close_button_(new OverviewCloseButton(this)), - selector_item_activate_window_button_( - new TransparentActivateWindowButton(root_window_, this)) { + overview_window_button_(new OverviewWindowButton(window)) { views::Widget::InitParams params; params.type = views::Widget::InitParams::TYPE_POPUP; params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; @@ -179,7 +146,7 @@ base::AutoReset<bool> auto_reset_in_bounds_update(&in_bounds_update_, true); target_bounds_ = target_bounds; - UpdateWindowLabels(target_bounds, animation_type); + overview_window_button_->SetBounds(target_bounds, animation_type); gfx::Rect inset_bounds(target_bounds); inset_bounds.Inset(kWindowMargin, kWindowMargin); @@ -188,7 +155,6 @@ // SetItemBounds is called before UpdateCloseButtonLayout so the close button // can properly use the updated windows bounds. UpdateCloseButtonLayout(animation_type); - UpdateSelectorButtons(); } void WindowSelectorItem::RecomputeWindowTransforms() { @@ -198,13 +164,11 @@ gfx::Rect inset_bounds(target_bounds_); inset_bounds.Inset(kWindowMargin, kWindowMargin); SetItemBounds(inset_bounds, OverviewAnimationType::OVERVIEW_ANIMATION_NONE); - UpdateCloseButtonLayout(OverviewAnimationType::OVERVIEW_ANIMATION_NONE); - UpdateSelectorButtons(); } void WindowSelectorItem::SendFocusAlert() const { - selector_item_activate_window_button_->SendFocusAlert(); + overview_window_button_->SendFocusAlert(); } void WindowSelectorItem::SetDimmed(bool dimmed) { @@ -225,18 +189,8 @@ void WindowSelectorItem::OnWindowTitleChanged(aura::Window* window) { // TODO(flackr): Maybe add the new title to a vector of titles so that we can // filter any of the titles the window had while in the overview session. - if (window == GetWindow()) { - window_label_view_->SetText(window->title()); - UpdateCloseButtonAccessibilityName(); - } - UpdateCloseButtonLayout(OverviewAnimationType::OVERVIEW_ANIMATION_NONE); - UpdateSelectorButtons(); -} - -void WindowSelectorItem::Select() { - aura::Window* selection_window = GetWindow(); - if (selection_window) - wm::GetWindowState(selection_window)->Activate(); + overview_window_button_->SetLabelText(window->title()); + UpdateCloseButtonAccessibilityName(); } void WindowSelectorItem::SetItemBounds(const gfx::Rect& target_bounds, @@ -256,87 +210,18 @@ } void WindowSelectorItem::SetOpacity(float opacity) { - window_label_->GetNativeWindow()->layer()->SetOpacity(opacity); + overview_window_button_->SetOpacity(opacity); close_button_widget_.GetNativeWindow()->layer()->SetOpacity(opacity); transform_window_.SetOpacity(opacity); } -void WindowSelectorItem::UpdateWindowLabels( - const gfx::Rect& window_bounds, - OverviewAnimationType animation_type) { - - if (!window_label_) { - CreateWindowLabel(GetWindow()->title()); - SetupFadeInAfterLayout(window_label_->GetNativeWindow()); - } - - gfx::Rect converted_bounds = ScreenUtil::ConvertRectFromScreen(root_window_, - window_bounds); - gfx::Rect label_bounds(converted_bounds.x(), - converted_bounds.bottom(), - converted_bounds.width(), - 0); - label_bounds.set_height(window_label_->GetContentsView()-> - GetPreferredSize().height()); - label_bounds.set_y(label_bounds.y() - window_label_-> - GetContentsView()->GetPreferredSize().height()); - - ScopedOverviewAnimationSettings animation_settings(animation_type, - window_label_->GetNativeWindow()); - - window_label_->GetNativeWindow()->SetBounds(label_bounds); -} - -void WindowSelectorItem::CreateWindowLabel(const base::string16& title) { - window_label_.reset(new views::Widget); - views::Widget::InitParams params; - params.type = views::Widget::InitParams::TYPE_POPUP; - params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; - params.parent = Shell::GetContainer(root_window_, - kShellWindowId_OverlayContainer); - params.accept_events = false; - params.visible_on_all_workspaces = true; - window_label_->set_focus_on_creation(false); - window_label_->Init(params); - window_label_view_ = new views::Label; - window_label_view_->SetEnabledColor(kLabelColor); - window_label_view_->SetBackgroundColor(kLabelBackground); - window_label_view_->SetShadows(gfx::ShadowValues( - 1, - gfx::ShadowValue( - gfx::Point(0, kVerticalShadowOffset), kShadowBlur, kLabelShadow))); - ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); - window_label_view_->SetFontList( - bundle.GetFontList(ui::ResourceBundle::BoldFont)); - window_label_view_->SetText(title); - views::BoxLayout* layout = new views::BoxLayout(views::BoxLayout::kVertical, - 0, - kVerticalLabelPadding, - 0); - window_label_view_->SetLayoutManager(layout); - window_label_->SetContentsView(window_label_view_); - window_label_->Show(); -} - -void WindowSelectorItem::UpdateSelectorButtons() { - aura::Window* window = GetWindow(); - - selector_item_activate_window_button_->SetBounds(target_bounds()); - selector_item_activate_window_button_->SetAccessibleName(window->title()); - - TransparentActivateWindowButton* activate_button = - transform_window_.activate_button(); - activate_button->SetBounds(target_bounds()); - activate_button->SetAccessibleName(window->title()); -} - void WindowSelectorItem::UpdateCloseButtonLayout( OverviewAnimationType animation_type) { if (!close_button_->visible()) { close_button_->SetVisible(true); - SetupFadeInAfterLayout(close_button_widget_.GetNativeWindow()); + ScopedOverviewAnimationSettings::SetupFadeInAfterLayout( + close_button_widget_.GetNativeWindow()); } ScopedOverviewAnimationSettings animation_settings(animation_type, close_button_widget_.GetNativeWindow());
diff --git a/ash/wm/overview/window_selector_item.h b/ash/wm/overview/window_selector_item.h index 2af8c56..30157cc8 100644 --- a/ash/wm/overview/window_selector_item.h +++ b/ash/wm/overview/window_selector_item.h
@@ -7,10 +7,9 @@ #include "ash/ash_export.h" #include "ash/wm/overview/scoped_transform_overview_window.h" -#include "ash/wm/overview/transparent_activate_window_button.h" -#include "ash/wm/overview/transparent_activate_window_button_delegate.h" #include "base/compiler_specific.h" #include "base/memory/scoped_ptr.h" +#include "ui/aura/scoped_window_targeter.h" #include "ui/aura/window_observer.h" #include "ui/gfx/geometry/rect.h" #include "ui/views/controls/button/button.h" @@ -21,17 +20,17 @@ } namespace views { -class Label; +class LabelButton; class Widget; } namespace ash { +class OverviewWindowButton; + // This class represents an item in overview mode. -class ASH_EXPORT WindowSelectorItem - : public views::ButtonListener, - public aura::WindowObserver, - public TransparentActivateWindowButtonDelegate { +class ASH_EXPORT WindowSelectorItem : public views::ButtonListener, + public aura::WindowObserver { public: explicit WindowSelectorItem(aura::Window* window); ~WindowSelectorItem() override; @@ -83,9 +82,6 @@ void OnWindowDestroying(aura::Window* window) override; void OnWindowTitleChanged(aura::Window* window) override; - // ash::TransparentActivateWindowButtonDelegate: - void Select() override; - private: friend class WindowSelectorTest; @@ -98,19 +94,6 @@ // Changes the opacity of all the windows the item owns. void SetOpacity(float opacity); - // Updates the window label's bounds to |target_bounds|. Will create a new - // window label and fade it in if it doesn't exist. The bounds change is - // animated as specified by the |animation_type|. - void UpdateWindowLabels(const gfx::Rect& target_bounds, - OverviewAnimationType animation_type); - - // Initializes window_label_. - void CreateWindowLabel(const base::string16& title); - - // Updates the bounds and accessibility names for all the transparent - // overlays. - void UpdateSelectorButtons(); - // Updates the close button's bounds. Any change in bounds will be animated // from the current bounds to the new bounds as per the |animation_type|. void UpdateCloseButtonLayout(OverviewAnimationType animation_type); @@ -136,12 +119,6 @@ // a window layer for display on another monitor. bool in_bounds_update_; - // Label under the window displaying its active tab name. - scoped_ptr<views::Widget> window_label_; - - // View for the label under the window. - views::Label* window_label_view_; - // The close buttons widget container. views::Widget close_button_widget_; @@ -149,11 +126,8 @@ // close_button_widget_. views::ImageButton* close_button_; - // Transparent overlay that covers the entire bounds of the - // WindowSelectorItem and is stacked in front of all windows but behind each - // Windows' own TransparentActivateWindowButton. - scoped_ptr<TransparentActivateWindowButton> - selector_item_activate_window_button_; + // Button that handles window activation. + scoped_ptr<OverviewWindowButton> overview_window_button_; DISALLOW_COPY_AND_ASSIGN(WindowSelectorItem); };
diff --git a/ash/wm/overview/window_selector_unittest.cc b/ash/wm/overview/window_selector_unittest.cc index c3eb4f87..6a0fb862 100644 --- a/ash/wm/overview/window_selector_unittest.cc +++ b/ash/wm/overview/window_selector_unittest.cc
@@ -19,6 +19,7 @@ #include "ash/test/test_shelf_delegate.h" #include "ash/wm/maximize_mode/maximize_mode_controller.h" #include "ash/wm/mru_window_tracker.h" +#include "ash/wm/overview/overview_window_button.h" #include "ash/wm/overview/window_grid.h" #include "ash/wm/overview/window_selector.h" #include "ash/wm/overview/window_selector_controller.h" @@ -46,7 +47,7 @@ #include "ui/gfx/geometry/rect_conversions.h" #include "ui/gfx/transform.h" #include "ui/gfx/transform_util.h" -#include "ui/views/controls/label.h" +#include "ui/views/controls/button/label_button.h" #include "ui/views/widget/native_widget_aura.h" #include "ui/views/widget/widget_delegate.h" #include "ui/wm/core/window_util.h" @@ -214,8 +215,9 @@ return &(window->close_button_widget_); } - views::Label* GetLabelView(ash::WindowSelectorItem* window) { - return window->window_label_view_; + views::LabelButton* GetLabelButtonView(ash::WindowSelectorItem* window) { + return static_cast<views::LabelButton*>( + window->overview_window_button_->window_label_->GetContentsView()); } // Tests that a window is contained within a given WindowSelectorItem, and @@ -346,9 +348,9 @@ event_generator.PressTouchId(kTouchId); // Tap on the desktop, which should not cause a crash. Overview mode should - // remain engaged because the transparent widget over the window has capture. + // be disengaged. event_generator.GestureTapAt(gfx::Point(0, 0)); - EXPECT_TRUE(IsSelecting()); + EXPECT_FALSE(IsSelecting()); event_generator.ReleaseTouchId(kTouchId); } @@ -371,15 +373,16 @@ window1_bounds.CenterPoint()); // Clicking on |window2| while touching on |window1| should not cause a - // crash, and overview mode should remain engaged because |window1| - // has capture. + // crash, and |window2| should be selected. const int kTouchId = 19; event_generator.PressTouchId(kTouchId); event_generator.MoveMouseToCenterOf(window2.get()); event_generator.ClickLeftButton(); - EXPECT_TRUE(IsSelecting()); + EXPECT_FALSE(IsSelecting()); event_generator.ReleaseTouchId(kTouchId); + ToggleOverview(); + // Clicking on |window1| while touching on |window1| should not cause // a crash, overview mode should be disengaged, and |window1| should // be active. @@ -910,17 +913,17 @@ window->SetTitle(window_title); ToggleOverview(); WindowSelectorItem* window_item = GetWindowItemsForRoot(0).back(); - views::Label* label = GetLabelView(window_item); + views::LabelButton* label = GetLabelButtonView(window_item); // Has the label view been created? ASSERT_TRUE(label); // Verify the label matches the window title. - EXPECT_EQ(label->text(), window_title); + EXPECT_EQ(label->GetText(), window_title); // Update the window title and check that the label is updated, too. base::string16 updated_title = base::UTF8ToUTF16("Updated title"); window->SetTitle(updated_title); - EXPECT_EQ(label->text(), updated_title); + EXPECT_EQ(label->GetText(), updated_title); // Labels are located based on target_bounds, not the actual window item // bounds.
diff --git a/ash/wm/power_button_controller.cc b/ash/wm/power_button_controller.cc index 8a8d0e52..5d70803 100644 --- a/ash/wm/power_button_controller.cc +++ b/ash/wm/power_button_controller.cc
@@ -78,7 +78,7 @@ // immediately. if (down) { if (session_state_delegate->CanLockScreen() && - !session_state_delegate->IsScreenLocked() && + !session_state_delegate->IsUserSessionBlocked() && !controller_->LockRequested()) { controller_->StartLockAnimationAndLockImmediately(false); } else { @@ -92,7 +92,7 @@ return; if (session_state_delegate->CanLockScreen() && - !session_state_delegate->IsScreenLocked()) { + !session_state_delegate->IsUserSessionBlocked()) { if (Shell::GetInstance()->maximize_mode_controller()-> IsMaximizeModeWindowManagerEnabled() && enable_quick_lock_) controller_->StartLockAnimationAndLockImmediately(true);
diff --git a/ash/wm/window_animations.cc b/ash/wm/window_animations.cc index c1c5c68..dbd8bf3 100644 --- a/ash/wm/window_animations.cc +++ b/ash/wm/window_animations.cc
@@ -293,6 +293,7 @@ layer_owner_->root()->GetAnimator()->StopAnimating(); } void OnCompositingLockStateChanged(ui::Compositor* compositor) override {} + void OnCompositingShuttingDown(ui::Compositor* compositor) override {} // aura::WindowObserver overrides: void OnWindowDestroying(aura::Window* window) override {
diff --git a/base/BUILD.gn b/base/BUILD.gn index e20b744b..616e404 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -1172,7 +1172,6 @@ "debug/trace_event_synthetic_delay_unittest.cc", "debug/trace_event_system_stats_monitor_unittest.cc", "debug/trace_event_unittest.cc", - "debug/trace_event_unittest.h", "debug/trace_event_win_unittest.cc", "deferred_sequenced_task_runner_unittest.cc", "environment_unittest.cc",
diff --git a/base/allocator/allocator.gyp b/base/allocator/allocator.gyp index b379ec9..c20325d 100644 --- a/base/allocator/allocator.gyp +++ b/base/allocator/allocator.gyp
@@ -24,11 +24,6 @@ { 'target_name': 'allocator', 'type': 'static_library', - # Make sure the allocation library is optimized to - # the hilt in official builds. - 'variables': { - 'optimize': 'max', - }, 'direct_dependent_settings': { 'configurations': { 'Common_Base': {
diff --git a/base/allocator/allocator_shim_win.cc b/base/allocator/allocator_shim_win.cc index 1e7fe19..a1473e5 100644 --- a/base/allocator/allocator_shim_win.cc +++ b/base/allocator/allocator_shim_win.cc
@@ -253,4 +253,67 @@ return calloc(n, size); } +#ifndef NDEBUG +#undef malloc +#undef free +#undef calloc + +static int error_handler(int reportType) { + switch (reportType) { + case 0: // _CRT_WARN + __debugbreak(); + return 0; + + case 1: // _CRT_ERROR + __debugbreak(); + return 0; + + case 2: // _CRT_ASSERT + __debugbreak(); + return 0; + } + char* p = NULL; + *p = '\0'; + return 0; +} + +int _CrtDbgReport(int reportType, + const char*, + int, + const char*, + const char*, + ...) { + return error_handler(reportType); +} + +int _CrtDbgReportW(int reportType, + const wchar_t*, + int, + const wchar_t*, + const wchar_t*, + ...) { + return error_handler(reportType); +} + +int _CrtSetReportMode(int, int) { + return 0; +} + +void* _malloc_dbg(size_t size, int, const char*, int) { + return malloc(size); +} + +void* _realloc_dbg(void* ptr, size_t size, int, const char*, int) { + return realloc(ptr, size); +} + +void _free_dbg(void* ptr, int) { + free(ptr); +} + +void* _calloc_dbg(size_t n, size_t size, int, const char*, int) { + return calloc(n, size); +} +#endif // NDEBUG + } // extern C
diff --git a/base/android/java/src/org/chromium/base/metrics/RecordHistogram.java b/base/android/java/src/org/chromium/base/metrics/RecordHistogram.java index 8295a85..050708c 100644 --- a/base/android/java/src/org/chromium/base/metrics/RecordHistogram.java +++ b/base/android/java/src/org/chromium/base/metrics/RecordHistogram.java
@@ -21,7 +21,7 @@ * @param sample sample to be recorded, either true or false */ public static void recordBooleanHistogram(String name, boolean sample) { - nativeRecordBooleanHistogram(name, sample); + nativeRecordBooleanHistogram(name, System.identityHashCode(name), sample); } /** @@ -33,7 +33,7 @@ * lower than |boundary| */ public static void recordEnumeratedHistogram(String name, int sample, int boundary) { - nativeRecordEnumeratedHistogram(name, sample, boundary); + nativeRecordEnumeratedHistogram(name, System.identityHashCode(name), sample, boundary); } /** @@ -53,9 +53,9 @@ nativeInitialize(); } - private static native void nativeRecordBooleanHistogram(String name, boolean sample); + private static native void nativeRecordBooleanHistogram(String name, int key, boolean sample); private static native void nativeRecordEnumeratedHistogram( - String name, int sample, int boundary); + String name, int key, int sample, int boundary); private static native int nativeGetHistogramValueCountForTesting(String name, int sample); private static native void nativeInitialize();
diff --git a/base/android/record_histogram.cc b/base/android/record_histogram.cc index 9a72460..9549adc2 100644 --- a/base/android/record_histogram.cc +++ b/base/android/record_histogram.cc
@@ -2,39 +2,108 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/android/record_histogram.h" + +#include <map> + #include "base/android/jni_android.h" #include "base/android/jni_string.h" -#include "base/android/record_histogram.h" +#include "base/lazy_instance.h" #include "base/metrics/histogram.h" #include "base/metrics/statistics_recorder.h" +#include "base/synchronization/lock.h" #include "jni/RecordHistogram_jni.h" namespace base { namespace android { +namespace { + +// Simple thread-safe wrapper for caching histograms. This avoids +// relatively expensive JNI string translation for each recording. +class HistogramCache { + public: + HistogramCache() {} + + HistogramBase* BooleanHistogram(JNIEnv* env, + jstring j_histogram_name, + jint j_histogram_key) { + DCHECK(j_histogram_name); + DCHECK(j_histogram_key); + HistogramBase* histogram = FindLocked(j_histogram_key); + if (histogram) + return histogram; + + std::string histogram_name = ConvertJavaStringToUTF8(env, j_histogram_name); + histogram = BooleanHistogram::FactoryGet( + histogram_name, HistogramBase::kUmaTargetedHistogramFlag); + return InsertLocked(j_histogram_key, histogram); + } + + HistogramBase* EnumeratedHistogram(JNIEnv* env, + jstring j_histogram_name, + jint j_histogram_key, + jint j_boundary) { + DCHECK(j_histogram_name); + DCHECK(j_histogram_key); + HistogramBase* histogram = FindLocked(j_histogram_key); + if (histogram) + return histogram; + + std::string histogram_name = ConvertJavaStringToUTF8(env, j_histogram_name); + // Note: This caching bypasses the boundary validation that occurs between + // repeated lookups by the same name. It is up to the caller to ensure that + // the provided boundary remains consistent. + int boundary = static_cast<int>(j_boundary); + histogram = + LinearHistogram::FactoryGet(histogram_name, 1, boundary, boundary + 1, + HistogramBase::kUmaTargetedHistogramFlag); + return InsertLocked(j_histogram_key, histogram); + } + + private: + HistogramBase* FindLocked(jint j_histogram_key) { + base::AutoLock locked(lock_); + auto histogram_it = histograms_.find(j_histogram_key); + return histogram_it != histograms_.end() ? histogram_it->second : nullptr; + } + + HistogramBase* InsertLocked(jint j_histogram_key, HistogramBase* histogram) { + base::AutoLock locked(lock_); + histograms_.insert(std::make_pair(j_histogram_key, histogram)); + return histogram; + } + + base::Lock lock_; + std::map<jint, HistogramBase*> histograms_; + + DISALLOW_COPY_AND_ASSIGN(HistogramCache); +}; + +base::LazyInstance<HistogramCache>::Leaky g_histograms; + +} // namespace void RecordBooleanHistogram(JNIEnv* env, jclass clazz, jstring j_histogram_name, + jint j_histogram_key, jboolean j_sample) { - std::string histogram_name = ConvertJavaStringToUTF8(env, j_histogram_name); bool sample = static_cast<bool>(j_sample); - - BooleanHistogram::FactoryGet(histogram_name, - HistogramBase::kUmaTargetedHistogramFlag) + g_histograms.Get() + .BooleanHistogram(env, j_histogram_name, j_histogram_key) ->AddBoolean(sample); } void RecordEnumeratedHistogram(JNIEnv* env, jclass clazz, jstring j_histogram_name, + jint j_histogram_key, jint j_sample, jint j_boundary) { - std::string histogram_name = ConvertJavaStringToUTF8(env, j_histogram_name); int sample = static_cast<int>(j_sample); - int boundary = static_cast<int>(j_boundary); - LinearHistogram::FactoryGet(histogram_name, 1, boundary, boundary + 1, - HistogramBase::kUmaTargetedHistogramFlag) + g_histograms.Get() + .EnumeratedHistogram(env, j_histogram_name, j_histogram_key, j_boundary) ->Add(sample); }
diff --git a/base/base.gyp b/base/base.gyp index 114cad6..c5b28c4 100644 --- a/base/base.gyp +++ b/base/base.gyp
@@ -487,7 +487,6 @@ 'debug/trace_event_synthetic_delay_unittest.cc', 'debug/trace_event_system_stats_monitor_unittest.cc', 'debug/trace_event_unittest.cc', - 'debug/trace_event_unittest.h', 'debug/trace_event_win_unittest.cc', 'deferred_sequenced_task_runner_unittest.cc', 'environment_unittest.cc', @@ -929,8 +928,6 @@ 'test/mock_chrome_application_mac.mm', 'test/mock_devices_changed_observer.cc', 'test/mock_devices_changed_observer.h', - 'test/mock_time_provider.cc', - 'test/mock_time_provider.h', 'test/multiprocess_test.cc', 'test/multiprocess_test.h', 'test/multiprocess_test_android.cc',
diff --git a/base/base.gypi b/base/base.gypi index 0c6ee7e..1d19597 100644 --- a/base/base.gypi +++ b/base/base.gypi
@@ -779,6 +779,7 @@ 'allocator/type_profiler_control.h', 'base_paths.cc', 'cpu.cc', + 'debug/stack_trace.cc', 'debug/stack_trace_posix.cc', 'files/file_enumerator_posix.cc', 'files/file_path_watcher_fsevents.cc', @@ -789,17 +790,22 @@ 'files/file_util.cc', 'files/file_util_posix.cc', 'files/file_util_proxy.cc', + 'files/important_file_writer.cc', 'memory/shared_memory_posix.cc', 'native_library_posix.cc', 'path_service.cc', 'posix/unix_domain_socket_linux.cc', + 'process/kill.cc', 'process/kill_posix.cc', + 'process/launch.cc', 'process/launch_posix.cc', + 'process/process_metrics.cc', 'process/process_metrics_posix.cc', 'process/process_posix.cc', 'rand_util_posix.cc', 'scoped_native_library.cc', 'files/scoped_temp_dir.cc', + 'sys_info.cc', 'sys_info_posix.cc', 'third_party/dynamic_annotations/dynamic_annotations.c', ],
diff --git a/base/base.isolate b/base/base.isolate index 0416935e..c23fdd4 100644 --- a/base/base.isolate +++ b/base/base.isolate
@@ -23,9 +23,17 @@ ], }, }], + ['OS=="win" and asan==1', { + 'variables': { + 'files': [ + '../third_party/llvm-build/Release+Asserts/lib/clang/3.7.0/lib/windows/clang_rt.asan_dynamic-i386.dll', + ], + }, + }], ['OS=="linux" and asan==1', { 'variables': { 'files': [ + # For llvm-symbolizer. '../third_party/llvm-build/Release+Asserts/lib/libstdc++.so.6', ], }, @@ -34,7 +42,7 @@ 'variables': { 'files': [ '../tools/valgrind/asan/', - '../third_party/llvm-build/Release+Asserts/bin/llvm-symbolizer', + '../third_party/llvm-build/Release+Asserts/bin/llvm-symbolizer<(EXECUTABLE_SUFFIX)', ], }, }],
diff --git a/base/debug/trace_event_synthetic_delay.cc b/base/debug/trace_event_synthetic_delay.cc index 6abfe18..260a5d8 100644 --- a/base/debug/trace_event_synthetic_delay.cc +++ b/base/debug/trace_event_synthetic_delay.cc
@@ -184,7 +184,7 @@ } base::TimeTicks TraceEventSyntheticDelayRegistry::Now() { - return base::TimeTicks::HighResNow(); + return base::TimeTicks::Now(); } void TraceEventSyntheticDelayRegistry::ResetAllDelays() {
diff --git a/base/debug/trace_event_unittest.cc b/base/debug/trace_event_unittest.cc index 30ad797..4494c99f 100644 --- a/base/debug/trace_event_unittest.cc +++ b/base/debug/trace_event_unittest.cc
@@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/debug/trace_event_unittest.h" - #include <math.h> #include <cstdlib> @@ -871,13 +869,6 @@ } // namespace -void HighResSleepForTraceTest(base::TimeDelta elapsed) { - base::TimeTicks end_time = base::TimeTicks::HighResNow() + elapsed; - do { - base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(1)); - } while (base::TimeTicks::HighResNow() < end_time); -} - // Simple Test for emitting data and validating it was received. TEST_F(TraceEventTestFixture, DataCaptured) { TraceLog::GetInstance()->SetEnabled(
diff --git a/base/debug/trace_event_unittest.h b/base/debug/trace_event_unittest.h deleted file mode 100644 index 599fec7d..0000000 --- a/base/debug/trace_event_unittest.h +++ /dev/null
@@ -1,14 +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 "base/time/time.h" - -namespace base { -namespace debug { - -// Sleep until HighResNow has advanced by at least |elapsed|. -void HighResSleepForTraceTest(base::TimeDelta elapsed); - -} // namespace debug -} // namespace base
diff --git a/base/memory/discardable_memory_shmem_allocator.cc b/base/memory/discardable_memory_shmem_allocator.cc index fdd6867..8abe4569 100644 --- a/base/memory/discardable_memory_shmem_allocator.cc +++ b/base/memory/discardable_memory_shmem_allocator.cc
@@ -18,7 +18,11 @@ : shared_memory_(shared_memory.Pass()) {} // Overridden from DiscardableMemoryShmemChunk: - bool Lock() override { return shared_memory_->Lock(0, 0); } + bool Lock() override { + auto result = shared_memory_->Lock(0, 0); + DCHECK_NE(result, DiscardableSharedMemory::PURGED); + return result == DiscardableSharedMemory::SUCCESS; + } void Unlock() override { shared_memory_->Unlock(0, 0); } void* Memory() const override { return shared_memory_->memory(); } bool IsMemoryResident() const override {
diff --git a/base/memory/discardable_shared_memory.cc b/base/memory/discardable_shared_memory.cc index e04377ee..3805bed 100644 --- a/base/memory/discardable_shared_memory.cc +++ b/base/memory/discardable_shared_memory.cc
@@ -157,7 +157,8 @@ return true; } -bool DiscardableSharedMemory::Lock(size_t offset, size_t length) { +DiscardableSharedMemory::LockResult DiscardableSharedMemory::Lock( + size_t offset, size_t length) { DCHECK_EQ(AlignToPageSize(offset), offset); DCHECK_EQ(AlignToPageSize(length), length); @@ -167,7 +168,7 @@ // Return false when instance has been purged or not initialized properly by // checking if |last_known_usage_| is NULL. if (last_known_usage_.is_null()) - return false; + return FAILED; DCHECK(shared_memory_.memory()); @@ -184,7 +185,7 @@ // Update |last_known_usage_| in case the above CAS failed because of // an incorrect timestamp. last_known_usage_ = result.GetTimestamp(); - return false; + return FAILED; } } @@ -214,11 +215,11 @@ DCHECK(SharedMemory::IsHandleValid(handle)); if (ashmem_pin_region( handle.fd, AlignToPageSize(sizeof(SharedState)) + offset, length)) { - return false; + return PURGED; } #endif - return true; + return SUCCESS; } void DiscardableSharedMemory::Unlock(size_t offset, size_t length) {
diff --git a/base/memory/discardable_shared_memory.h b/base/memory/discardable_shared_memory.h index abee8687..59c5d5b5 100644 --- a/base/memory/discardable_shared_memory.h +++ b/base/memory/discardable_shared_memory.h
@@ -23,6 +23,8 @@ // access to an instance of this class. class BASE_EXPORT DiscardableSharedMemory { public: + enum LockResult { SUCCESS, PURGED, FAILED }; + DiscardableSharedMemory(); // Create a new DiscardableSharedMemory object from an existing, open shared @@ -47,16 +49,18 @@ SharedMemoryHandle handle() const { return shared_memory_.handle(); } // Locks a range of memory so that it will not be purged by the system. - // Returns true if successful and the memory is still resident. Locking can - // fail for three reasons; object might have been purged, our last known usage - // timestamp might be out of date or memory might already be locked. Last - // know usage time is updated to the actual last usage timestamp if memory - // is still resident or 0 if not. The range of memory must be unlocked. The - // result of trying to lock an already locked range is undefined. - // |offset| and |length| must both be a multiple of the page size as returned - // by GetPageSize(). + // The range of memory must be unlocked. The result of trying to lock an + // already locked range is undefined. |offset| and |length| must both be + // a multiple of the page size as returned by GetPageSize(). // Passing 0 for |length| means "everything onward". - bool Lock(size_t offset, size_t length); + // Returns SUCCESS if range was successfully locked and the memory is still + // resident, PURGED if range was successfully locked but has been purged + // since last time it was locked and FAILED if range could not be locked. + // Locking can fail for two reasons; object might have been purged, our + // last known usage timestamp might be out of date. Last known usage time + // is updated to the actual last usage timestamp if memory is still resident + // or 0 if not. + LockResult Lock(size_t offset, size_t length); // Unlock a previously successfully locked range of memory. The range of // memory must be locked. The result of trying to unlock a not
diff --git a/base/memory/discardable_shared_memory_unittest.cc b/base/memory/discardable_shared_memory_unittest.cc index 896263d..1f08aea8 100644 --- a/base/memory/discardable_shared_memory_unittest.cc +++ b/base/memory/discardable_shared_memory_unittest.cc
@@ -64,14 +64,14 @@ memory1.Unlock(0, 0); // Lock and unlock memory. - rv = memory1.Lock(0, 0); - EXPECT_TRUE(rv); + auto lock_rv = memory1.Lock(0, 0); + EXPECT_EQ(DiscardableSharedMemory::SUCCESS, lock_rv); memory1.SetNow(Time::FromDoubleT(2)); memory1.Unlock(0, 0); // Lock again before duplicating and passing ownership to new instance. - rv = memory1.Lock(0, 0); - EXPECT_TRUE(rv); + lock_rv = memory1.Lock(0, 0); + EXPECT_EQ(DiscardableSharedMemory::SUCCESS, lock_rv); SharedMemoryHandle shared_handle; ASSERT_TRUE( @@ -87,8 +87,8 @@ memory2.Unlock(0, 0); // Lock second instance before passing ownership back to first instance. - rv = memory2.Lock(0, 0); - EXPECT_TRUE(rv); + lock_rv = memory2.Lock(0, 0); + EXPECT_EQ(DiscardableSharedMemory::SUCCESS, lock_rv); // Memory should still be resident. rv = memory1.IsMemoryResident(); @@ -135,8 +135,8 @@ EXPECT_TRUE(rv); // Lock should fail as memory has been purged. - rv = memory2.Lock(0, 0); - EXPECT_FALSE(rv); + auto lock_rv = memory2.Lock(0, 0); + EXPECT_EQ(DiscardableSharedMemory::FAILED, lock_rv); ASSERT_FALSE(memory2.IsMemoryResident()); } @@ -162,8 +162,8 @@ EXPECT_EQ(memory2.last_known_usage(), Time::FromDoubleT(1)); - rv = memory2.Lock(0, 0); - EXPECT_TRUE(rv); + auto lock_rv = memory2.Lock(0, 0); + EXPECT_EQ(DiscardableSharedMemory::SUCCESS, lock_rv); // This should fail as memory is locked. rv = memory1.Purge(Time::FromDoubleT(2)); @@ -232,10 +232,10 @@ EXPECT_TRUE(rv); // Lock should fail as memory has been purged. - rv = memory2.Lock(0, 0); - EXPECT_FALSE(rv); - rv = memory1.Lock(0, 0); - EXPECT_FALSE(rv); + auto lock_rv = memory2.Lock(0, 0); + EXPECT_EQ(DiscardableSharedMemory::FAILED, lock_rv); + lock_rv = memory1.Lock(0, 0); + EXPECT_EQ(DiscardableSharedMemory::FAILED, lock_rv); } TEST(DiscardableSharedMemoryTest, LockAndUnlockRange) {
diff --git a/base/message_loop/message_pump_perftest.cc b/base/message_loop/message_pump_perftest.cc index 39ed5a8..b3e5604 100644 --- a/base/message_loop/message_pump_perftest.cc +++ b/base/message_loop/message_pump_perftest.cc
@@ -29,7 +29,7 @@ void Increment(uint64_t amount) { counter_ += amount; } void Schedule(int index) { - base::TimeTicks start = base::TimeTicks::HighResNow(); + base::TimeTicks start = base::TimeTicks::Now(); base::TimeTicks thread_start; if (TimeTicks::IsThreadNowSupported()) thread_start = base::TimeTicks::ThreadNow(); @@ -42,7 +42,7 @@ target_message_loop()->ScheduleWork(); schedule_calls++; } - now = base::TimeTicks::HighResNow(); + now = base::TimeTicks::Now(); base::TimeDelta laptime = now - lastnow; lastnow = now; minimum = std::min(minimum, laptime); @@ -242,7 +242,7 @@ class PostTaskTest : public testing::Test { public: void Run(int batch_size, int tasks_per_reload) { - base::TimeTicks start = base::TimeTicks::HighResNow(); + base::TimeTicks start = base::TimeTicks::Now(); base::TimeTicks now; MessageLoop loop(scoped_ptr<MessagePump>(new FakeMessagePump)); scoped_refptr<internal::IncomingTaskQueue> queue( @@ -264,7 +264,7 @@ } } - now = base::TimeTicks::HighResNow(); + now = base::TimeTicks::Now(); } while (now - start < base::TimeDelta::FromSeconds(5)); std::string trace = StringPrintf("%d_tasks_per_reload", tasks_per_reload); perf_test::PrintResult(
diff --git a/base/numerics/safe_numerics_unittest.cc b/base/numerics/safe_numerics_unittest.cc index 0402cef2..bdececb 100644 --- a/base/numerics/safe_numerics_unittest.cc +++ b/base/numerics/safe_numerics_unittest.cc
@@ -26,14 +26,6 @@ using base::internal::RANGE_UNDERFLOW; using base::enable_if; -// MSVS 2013 ia32 may not reset the FPU between calculations, and the test -// framework masks the exceptions. So we just force a manual reset after NaN. -inline void ResetFloatingPointUnit() { -#if defined(COMPILER_MSVC) && defined(ARCH_CPU_32_BITS) - _mm_empty(); -#endif -} - // These tests deliberately cause arithmetic overflows. If the compiler is // aggressive enough, it can const fold these overflows. Disable warnings about // overflows for const expressions. @@ -341,7 +333,6 @@ TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity()); TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1); TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN()); - ResetFloatingPointUnit(); } else if (numeric_limits<Src>::is_signed) { TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1)); TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::min()); @@ -373,7 +364,6 @@ TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity()); TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1); TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN()); - ResetFloatingPointUnit(); } else if (SrcLimits::is_signed) { TEST_EXPECTED_VALUE(-1, checked_dst - static_cast<Src>(1)); TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::min()); @@ -432,7 +422,6 @@ TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity()); TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1); TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN()); - ResetFloatingPointUnit(); } else { TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::min()); }
diff --git a/base/process/kill_mac.cc b/base/process/kill_mac.cc index a2632f6..8c424009 100644 --- a/base/process/kill_mac.cc +++ b/base/process/kill_mac.cc
@@ -166,7 +166,7 @@ } // namespace void EnsureProcessTerminated(Process process) { - WaitForChildToDie(process.pid(), kWaitBeforeKillSeconds); + WaitForChildToDie(process.Pid(), kWaitBeforeKillSeconds); } } // namespace base
diff --git a/base/process/kill_posix.cc b/base/process/kill_posix.cc index 9e9b5fb0..5e8b61f 100644 --- a/base/process/kill_posix.cc +++ b/base/process/kill_posix.cc
@@ -465,11 +465,11 @@ void EnsureProcessTerminated(Process process) { // If the child is already dead, then there's nothing to do. - if (IsChildDead(process.pid())) + if (IsChildDead(process.Pid())) return; const unsigned timeout = 2; // seconds - BackgroundReaper* reaper = new BackgroundReaper(process.pid(), timeout); + BackgroundReaper* reaper = new BackgroundReaper(process.Pid(), timeout); PlatformThread::CreateNonJoinable(0, reaper); }
diff --git a/base/process/process.h b/base/process/process.h index d556d8e0..70aca6d 100644 --- a/base/process/process.h +++ b/base/process/process.h
@@ -54,6 +54,12 @@ // address space and duplicate handles). static Process OpenWithExtraPriviles(ProcessId pid); +#if defined(OS_WIN) + // Returns a Process for the given |pid|, using some |desired_access|. + // See ::OpenProcess documentation for valid |desired_access|. + static Process OpenWithAccess(ProcessId pid, DWORD desired_access); +#endif + // Creates an object from a |handle| owned by someone else. // Don't use this for new code. It is only intended to ease the migration to // a strict ownership model. @@ -74,7 +80,7 @@ Process Duplicate() const; // Get the PID for this process. - ProcessId pid() const; + ProcessId Pid() const; // Returns true if this process is the current process. bool is_current() const;
diff --git a/base/process/process_handle.h b/base/process/process_handle.h index 368f952..976552c 100644 --- a/base/process/process_handle.h +++ b/base/process/process_handle.h
@@ -44,12 +44,6 @@ // CloseProcessHandle when you are done with it. Returns true on success. BASE_EXPORT bool OpenProcessHandle(ProcessId pid, ProcessHandle* handle); -// Converts a PID to a process handle using the desired access flags. Use a -// combination of the kProcessAccess* flags defined above for |access_flags|. -BASE_EXPORT bool OpenProcessHandleWithAccess(ProcessId pid, - uint32 access_flags, - ProcessHandle* handle); - // Closes the process handle opened by OpenProcessHandle. BASE_EXPORT void CloseProcessHandle(ProcessHandle process);
diff --git a/base/process/process_handle_posix.cc b/base/process/process_handle_posix.cc index 94b2c2ff..3d92300 100644 --- a/base/process/process_handle_posix.cc +++ b/base/process/process_handle_posix.cc
@@ -23,14 +23,6 @@ return true; } -bool OpenProcessHandleWithAccess(ProcessId pid, - uint32 access_flags, - ProcessHandle* handle) { - // On POSIX permissions are checked for each operation on process, - // not when opening a "handle". - return OpenProcessHandle(pid, handle); -} - void CloseProcessHandle(ProcessHandle process) { // See OpenProcessHandle, nothing to do. return;
diff --git a/base/process/process_handle_win.cc b/base/process/process_handle_win.cc index 595d5b0..468331163 100644 --- a/base/process/process_handle_win.cc +++ b/base/process/process_handle_win.cc
@@ -36,18 +36,6 @@ return true; } -bool OpenProcessHandleWithAccess(ProcessId pid, - uint32 access_flags, - ProcessHandle* handle) { - ProcessHandle result = OpenProcess(access_flags, FALSE, pid); - - if (result == NULL) - return false; - - *handle = result; - return true; -} - void CloseProcessHandle(ProcessHandle process) { CloseHandle(process); }
diff --git a/base/process/process_iterator.h b/base/process/process_iterator.h index bdd07c6..ec6500e6 100644 --- a/base/process/process_iterator.h +++ b/base/process/process_iterator.h
@@ -36,26 +36,6 @@ ProcessId parent_pid() const { return th32ParentProcessID; } const wchar_t* exe_file() const { return szExeFile; } }; - -// Process access masks. These constants provide platform-independent -// definitions for the standard Windows access masks. -// See http://msdn.microsoft.com/en-us/library/ms684880(VS.85).aspx for -// the specific semantics of each mask value. -const uint32 kProcessAccessTerminate = PROCESS_TERMINATE; -const uint32 kProcessAccessCreateThread = PROCESS_CREATE_THREAD; -const uint32 kProcessAccessSetSessionId = PROCESS_SET_SESSIONID; -const uint32 kProcessAccessVMOperation = PROCESS_VM_OPERATION; -const uint32 kProcessAccessVMRead = PROCESS_VM_READ; -const uint32 kProcessAccessVMWrite = PROCESS_VM_WRITE; -const uint32 kProcessAccessDuplicateHandle = PROCESS_DUP_HANDLE; -const uint32 kProcessAccessCreateProcess = PROCESS_CREATE_PROCESS; -const uint32 kProcessAccessSetQuota = PROCESS_SET_QUOTA; -const uint32 kProcessAccessSetInformation = PROCESS_SET_INFORMATION; -const uint32 kProcessAccessQueryInformation = PROCESS_QUERY_INFORMATION; -const uint32 kProcessAccessSuspendResume = PROCESS_SUSPEND_RESUME; -const uint32 kProcessAccessQueryLimitedInfomation = - PROCESS_QUERY_LIMITED_INFORMATION; -const uint32 kProcessAccessWaitForTermination = SYNCHRONIZE; #elif defined(OS_POSIX) struct BASE_EXPORT ProcessEntry { ProcessEntry(); @@ -75,23 +55,6 @@ std::string exe_file_; std::vector<std::string> cmd_line_args_; }; - -// Process access masks. They are not used on Posix because access checking -// does not happen during handle creation. -const uint32 kProcessAccessTerminate = 0; -const uint32 kProcessAccessCreateThread = 0; -const uint32 kProcessAccessSetSessionId = 0; -const uint32 kProcessAccessVMOperation = 0; -const uint32 kProcessAccessVMRead = 0; -const uint32 kProcessAccessVMWrite = 0; -const uint32 kProcessAccessDuplicateHandle = 0; -const uint32 kProcessAccessCreateProcess = 0; -const uint32 kProcessAccessSetQuota = 0; -const uint32 kProcessAccessSetInformation = 0; -const uint32 kProcessAccessQueryInformation = 0; -const uint32 kProcessAccessSuspendResume = 0; -const uint32 kProcessAccessQueryLimitedInfomation = 0; -const uint32 kProcessAccessWaitForTermination = 0; #endif // defined(OS_POSIX) // Used to filter processes by process ID.
diff --git a/base/process/process_metrics.h b/base/process/process_metrics.h index d011958e..5916b94 100644 --- a/base/process/process_metrics.h +++ b/base/process/process_metrics.h
@@ -143,6 +143,14 @@ // usage in bytes, as per definition of WorkingSetBytes. bool GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const; +#if defined(OS_MACOSX) + // Fills both CommitedKBytes and WorkingSetKBytes in a single operation. This + // is more efficient on Mac OS X, as the two can be retrieved with a single + // system call. + bool GetCommittedAndWorkingSetKBytes(CommittedKBytes* usage, + WorkingSetKBytes* ws_usage) const; +#endif + // Returns the CPU usage in percent since the last time this method or // GetPlatformIndependentCPUUsage() was called. The first time this method // is called it returns 0 and will return the actual CPU info on subsequent
diff --git a/base/process/process_metrics_mac.cc b/base/process/process_metrics_mac.cc index a07d3cd1..f84b435 100644 --- a/base/process/process_metrics_mac.cc +++ b/base/process/process_metrics_mac.cc
@@ -209,15 +209,32 @@ } void ProcessMetrics::GetCommittedKBytes(CommittedKBytes* usage) const { + WorkingSetKBytes unused; + if (!GetCommittedAndWorkingSetKBytes(usage, &unused)) { + *usage = CommittedKBytes(); + } } bool ProcessMetrics::GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const { - size_t priv = GetWorkingSetSize(); - if (!priv) + CommittedKBytes unused; + return GetCommittedAndWorkingSetKBytes(&unused, ws_usage); +} + +bool ProcessMetrics::GetCommittedAndWorkingSetKBytes( + CommittedKBytes* usage, + WorkingSetKBytes* ws_usage) const { + task_basic_info_64 task_info_data; + if (!GetTaskInfo(TaskForPid(process_), &task_info_data)) return false; - ws_usage->priv = priv / 1024; + + usage->priv = task_info_data.virtual_size / 1024; + usage->mapped = 0; + usage->image = 0; + + ws_usage->priv = task_info_data.resident_size / 1024; ws_usage->shareable = 0; ws_usage->shared = 0; + return true; }
diff --git a/base/process/process_posix.cc b/base/process/process_posix.cc index 93dec98a0..5d7007c 100644 --- a/base/process/process_posix.cc +++ b/base/process/process_posix.cc
@@ -75,7 +75,7 @@ return Process(process_); } -ProcessId Process::pid() const { +ProcessId Process::Pid() const { DCHECK(IsValid()); return GetProcId(process_); }
diff --git a/base/process/process_unittest.cc b/base/process/process_unittest.cc index 1a2af50..4ea7a5e 100644 --- a/base/process/process_unittest.cc +++ b/base/process/process_unittest.cc
@@ -68,7 +68,7 @@ Process process2 = process1.Duplicate(); ASSERT_TRUE(process1.IsValid()); ASSERT_TRUE(process2.IsValid()); - EXPECT_EQ(process1.pid(), process2.pid()); + EXPECT_EQ(process1.Pid(), process2.Pid()); EXPECT_FALSE(process1.is_current()); EXPECT_FALSE(process2.is_current()); @@ -83,7 +83,7 @@ Process process2 = process1.Duplicate(); ASSERT_TRUE(process1.IsValid()); ASSERT_TRUE(process2.IsValid()); - EXPECT_EQ(process1.pid(), process2.pid()); + EXPECT_EQ(process1.Pid(), process2.Pid()); EXPECT_TRUE(process1.is_current()); EXPECT_TRUE(process2.is_current()); @@ -98,7 +98,7 @@ Process process2 = Process::DeprecatedGetProcessFromHandle(process1.Handle()); ASSERT_TRUE(process1.IsValid()); ASSERT_TRUE(process2.IsValid()); - EXPECT_EQ(process1.pid(), process2.pid()); + EXPECT_EQ(process1.Pid(), process2.Pid()); EXPECT_FALSE(process1.is_current()); EXPECT_FALSE(process2.is_current());
diff --git a/base/process/process_util_unittest.cc b/base/process/process_util_unittest.cc index 88b4af3..33cf00f 100644 --- a/base/process/process_util_unittest.cc +++ b/base/process/process_util_unittest.cc
@@ -201,7 +201,7 @@ EXPECT_NE(0ul, id1); base::Process process = SpawnChild("SimpleChildProcess"); ASSERT_TRUE(process.IsValid()); - base::ProcessId id2 = process.pid(); + base::ProcessId id2 = process.Pid(); EXPECT_NE(0ul, id2); EXPECT_NE(id1, id2); }
diff --git a/base/process/process_win.cc b/base/process/process_win.cc index 2c267aa..0107015 100644 --- a/base/process/process_win.cc +++ b/base/process/process_win.cc
@@ -54,6 +54,11 @@ } // static +Process Process::OpenWithAccess(ProcessId pid, DWORD desired_access) { + return Process(::OpenProcess(desired_access, FALSE, pid)); +} + +// static Process Process::DeprecatedGetProcessFromHandle(ProcessHandle handle) { DCHECK_NE(handle, ::GetCurrentProcess()); ProcessHandle out_handle; @@ -95,7 +100,7 @@ return Process(out_handle); } -ProcessId Process::pid() const { +ProcessId Process::Pid() const { DCHECK(IsValid()); return GetProcId(Handle()); }
diff --git a/base/rand_util_unittest.cc b/base/rand_util_unittest.cc index d262275..90690ec2 100644 --- a/base/rand_util_unittest.cc +++ b/base/rand_util_unittest.cc
@@ -134,10 +134,10 @@ const size_t kTestBufferSize = 1 * 1024 * 1024; scoped_ptr<uint8[]> buffer(new uint8[kTestBufferSize]); - const base::TimeTicks now = base::TimeTicks::HighResNow(); + const base::TimeTicks now = base::TimeTicks::Now(); for (int i = 0; i < kTestIterations; ++i) base::RandBytes(buffer.get(), kTestBufferSize); - const base::TimeTicks end = base::TimeTicks::HighResNow(); + const base::TimeTicks end = base::TimeTicks::Now(); LOG(INFO) << "RandBytes(" << kTestBufferSize << ") took: " << (end - now).InMicroseconds() << "µs";
diff --git a/base/test/BUILD.gn b/base/test/BUILD.gn index b4987d9..cca72dd 100644 --- a/base/test/BUILD.gn +++ b/base/test/BUILD.gn
@@ -36,8 +36,6 @@ "mock_chrome_application_mac.mm", "mock_devices_changed_observer.cc", "mock_devices_changed_observer.h", - "mock_time_provider.cc", - "mock_time_provider.h", "multiprocess_test.cc", "multiprocess_test.h", "multiprocess_test_android.cc",
diff --git a/base/test/gtest_util.cc b/base/test/gtest_util.cc index f98320c..c0bc04a6 100644 --- a/base/test/gtest_util.cc +++ b/base/test/gtest_util.cc
@@ -11,6 +11,11 @@ namespace base { +std::string FormatFullTestName(const std::string& test_case_name, + const std::string& test_name) { + return test_case_name + "." + test_name; +} + std::vector<SplitTestName> GetCompiledInTests() { testing::UnitTest* const unit_test = testing::UnitTest::GetInstance();
diff --git a/base/test/gtest_util.h b/base/test/gtest_util.h index d10c72fc..77cc9249 100644 --- a/base/test/gtest_util.h +++ b/base/test/gtest_util.h
@@ -18,6 +18,11 @@ // First value is test case name, second one is test name. typedef std::pair<std::string, std::string> SplitTestName; +// Constructs a full test name given a test case name and a test name, +// e.g. for test case "A" and test name "B" returns "A.B". +std::string FormatFullTestName(const std::string& test_case_name, + const std::string& test_name); + // Returns a vector of gtest-based tests compiled into // current executable. std::vector<SplitTestName> GetCompiledInTests();
diff --git a/base/test/gtest_xml_util.cc b/base/test/gtest_xml_util.cc index 7a5ba8a8..db8cc2d 100644 --- a/base/test/gtest_xml_util.cc +++ b/base/test/gtest_xml_util.cc
@@ -7,6 +7,7 @@ #include "base/files/file_util.h" #include "base/logging.h" #include "base/strings/stringprintf.h" +#include "base/test/gtest_util.h" #include "base/test/launcher/test_launcher.h" #include "third_party/libxml/chromium/libxml_utils.h" @@ -146,8 +147,7 @@ std::string test_name; if (!xml_reader.NodeAttribute("name", &test_name)) return false; - result.full_name = TestLauncher::FormatFullTestName(test_case_name, - test_name); + result.full_name = FormatFullTestName(test_case_name, test_name); result.elapsed_time = TimeDelta();
diff --git a/base/test/launcher/test_launcher.cc b/base/test/launcher/test_launcher.cc index b5316ad8..667d1eb4 100644 --- a/base/test/launcher/test_launcher.cc +++ b/base/test/launcher/test_launcher.cc
@@ -686,12 +686,6 @@ test_started_count_ += retry_started_count; } -// static -std::string TestLauncher::FormatFullTestName(const std::string& test_case_name, - const std::string& test_name) { - return test_case_name + "." + test_name; -} - bool TestLauncher::Init() { const CommandLine* command_line = CommandLine::ForCurrentProcess();
diff --git a/base/test/launcher/test_launcher.h b/base/test/launcher/test_launcher.h index 27909d4..544df63 100644 --- a/base/test/launcher/test_launcher.h +++ b/base/test/launcher/test_launcher.h
@@ -115,10 +115,6 @@ // Called when a test has finished running. void OnTestFinished(const TestResult& result); - // Constructs a full test name given a test case name and a test name. - static std::string FormatFullTestName(const std::string& test_case_name, - const std::string& test_name); - private: bool Init() WARN_UNUSED_RESULT;
diff --git a/base/test/launcher/test_launcher_ios.cc b/base/test/launcher/test_launcher_ios.cc index 82353cc4..7028133 100644 --- a/base/test/launcher/test_launcher_ios.cc +++ b/base/test/launcher/test_launcher_ios.cc
@@ -15,6 +15,7 @@ #include "base/message_loop/message_loop.h" #include "base/path_service.h" #include "base/process/launch.h" +#include "base/strings/string_util.h" #include "base/test/launcher/unit_test_launcher.h" #include "base/test/test_switches.h" #include "base/test/test_timeouts.h" @@ -54,9 +55,9 @@ fflush(stdout); } -class IOSUnitTestLauncherDelegate : public base::UnitTestLauncherDelegate { +class IOSUnitTestPlatformDelegate : public base::UnitTestPlatformDelegate { public: - IOSUnitTestLauncherDelegate() : base::UnitTestLauncherDelegate(0, false) { + IOSUnitTestPlatformDelegate() { } bool Init() WARN_UNUSED_RESULT { @@ -107,6 +108,27 @@ return base::ReadTestNamesFromFile(test_list_path, output); } + bool CreateTemporaryFile(base::FilePath* path) override { + if (!CreateTemporaryDirInDir(writable_path_, std::string(), path)) + return false; + *path = path->AppendASCII("test_results.xml"); + return true; + } + + base::CommandLine GetCommandLineForChildGTestProcess( + const std::vector<std::string>& test_names, + const base::FilePath& output_file) override { + base::CommandLine cmd_line(dir_exe_.AppendASCII(test_name_ + ".app")); + cmd_line.AppendSwitchPath(switches::kTestLauncherOutput, output_file); + cmd_line.AppendSwitchASCII(base::kGTestFilterFlag, + JoinString(test_names, ":")); + return cmd_line; + } + + std::string GetWrapperForChildGTestProcess() override { + return dir_exe_.AppendASCII("iossim").value(); + } + private: // Directory containing test launcher's executable. base::FilePath dir_exe_; @@ -117,7 +139,7 @@ // Path that launched test binary can write to. base::FilePath writable_path_; - DISALLOW_COPY_AND_ASSIGN(IOSUnitTestLauncherDelegate); + DISALLOW_COPY_AND_ASSIGN(IOSUnitTestPlatformDelegate); }; } // namespace @@ -138,12 +160,13 @@ base::MessageLoopForIO message_loop; - IOSUnitTestLauncherDelegate delegate; - if (!delegate.Init()) { - fprintf(stderr, "Failed to intialize test launcher delegate.\n"); + IOSUnitTestPlatformDelegate platform_delegate; + if (!platform_delegate.Init()) { + fprintf(stderr, "Failed to intialize test launcher platform delegate.\n"); fflush(stderr); return 1; } + base::UnitTestLauncherDelegate delegate(&platform_delegate, 0, false); // Force one job since we can't run multiple simulators in parallel. base::TestLauncher launcher(&delegate, 1); bool success = launcher.Run();
diff --git a/base/test/launcher/unit_test_launcher.cc b/base/test/launcher/unit_test_launcher.cc index a31b6db..2a4e748 100644 --- a/base/test/launcher/unit_test_launcher.cc +++ b/base/test/launcher/unit_test_launcher.cc
@@ -85,20 +85,44 @@ fflush(stdout); } -// Returns command line for child GTest process based on the command line -// of current process. |test_names| is a vector of test full names -// (e.g. "A.B"), |output_file| is path to the GTest XML output file. -CommandLine GetCommandLineForChildGTestProcess( - const std::vector<std::string>& test_names, - const base::FilePath& output_file) { - CommandLine new_cmd_line(*CommandLine::ForCurrentProcess()); +class DefaultUnitTestPlatformDelegate : public UnitTestPlatformDelegate { + public: + DefaultUnitTestPlatformDelegate() { + } - new_cmd_line.AppendSwitchPath(switches::kTestLauncherOutput, output_file); - new_cmd_line.AppendSwitchASCII(kGTestFilterFlag, JoinString(test_names, ":")); - new_cmd_line.AppendSwitch(kSingleProcessTestsFlag); + private: + // UnitTestPlatformDelegate: + bool GetTests(std::vector<SplitTestName>* output) override { + *output = GetCompiledInTests(); + return true; + } - return new_cmd_line; -} + bool CreateTemporaryFile(base::FilePath* path) override { + if (!CreateNewTempDirectory(FilePath::StringType(), path)) + return false; + *path = path->AppendASCII("test_results.xml"); + return true; + } + + CommandLine GetCommandLineForChildGTestProcess( + const std::vector<std::string>& test_names, + const base::FilePath& output_file) override { + CommandLine new_cmd_line(*CommandLine::ForCurrentProcess()); + + new_cmd_line.AppendSwitchPath(switches::kTestLauncherOutput, output_file); + new_cmd_line.AppendSwitchASCII(kGTestFilterFlag, + JoinString(test_names, ":")); + new_cmd_line.AppendSwitch(kSingleProcessTestsFlag); + + return new_cmd_line; + } + + std::string GetWrapperForChildGTestProcess() override { + return std::string(); + } + + DISALLOW_COPY_AND_ASSIGN(DefaultUnitTestPlatformDelegate); +}; bool GetSwitchValueAsInt(const std::string& switch_name, int* result) { if (!CommandLine::ForCurrentProcess()->HasSwitch(switch_name)) @@ -169,7 +193,9 @@ MessageLoopForIO message_loop; - UnitTestLauncherDelegate delegate(batch_limit, use_job_objects); + DefaultUnitTestPlatformDelegate platform_delegate; + UnitTestLauncherDelegate delegate( + &platform_delegate, batch_limit, use_job_objects); base::TestLauncher launcher(&delegate, default_jobs); bool success = launcher.Run(); @@ -221,9 +247,13 @@ } #endif // defined(OS_WIN) -UnitTestLauncherDelegate::UnitTestLauncherDelegate(size_t batch_limit, - bool use_job_objects) - : batch_limit_(batch_limit), use_job_objects_(use_job_objects) { +UnitTestLauncherDelegate::UnitTestLauncherDelegate( + UnitTestPlatformDelegate* platform_delegate, + size_t batch_limit, + bool use_job_objects) + : platform_delegate_(platform_delegate), + batch_limit_(batch_limit), + use_job_objects_(use_job_objects) { } UnitTestLauncherDelegate::~UnitTestLauncherDelegate() { @@ -238,8 +268,7 @@ bool UnitTestLauncherDelegate::GetTests(std::vector<SplitTestName>* output) { DCHECK(thread_checker_.CalledOnValidThread()); - *output = GetCompiledInTests(); - return true; + return platform_delegate_->GetTests(output); } bool UnitTestLauncherDelegate::ShouldRunTest(const std::string& test_case_name, @@ -259,7 +288,8 @@ for (size_t i = 0; i < test_names.size(); i++) { batch.push_back(test_names[i]); - if (batch.size() >= batch_limit_) { + // Use 0 to indicate unlimited batch size. + if (batch.size() >= batch_limit_ && batch_limit_ != 0) { RunBatch(test_launcher, batch); batch.clear(); } @@ -293,13 +323,12 @@ // per run to ensure clean state and make it possible to launch multiple // processes in parallel. base::FilePath output_file; - CHECK(CreateNewTempDirectory(FilePath::StringType(), &output_file)); - output_file = output_file.AppendASCII("test_results.xml"); + CHECK(platform_delegate_->CreateTemporaryFile(&output_file)); std::vector<std::string> current_test_names; current_test_names.push_back(test_name); - CommandLine cmd_line( - GetCommandLineForChildGTestProcess(current_test_names, output_file)); + CommandLine cmd_line(platform_delegate_->GetCommandLineForChildGTestProcess( + current_test_names, output_file)); GTestCallbackState callback_state; callback_state.test_launcher = test_launcher; @@ -307,7 +336,9 @@ callback_state.output_file = output_file; test_launcher->LaunchChildGTestProcess( - cmd_line, std::string(), TestTimeouts::test_launcher_timeout(), + cmd_line, + platform_delegate_->GetWrapperForChildGTestProcess(), + TestTimeouts::test_launcher_timeout(), use_job_objects_ ? TestLauncher::USE_JOB_OBJECTS : 0, Bind(&UnitTestLauncherDelegate::SerialGTestCallback, Unretained(this), callback_state, new_test_names)); @@ -325,11 +356,10 @@ // per run to ensure clean state and make it possible to launch multiple // processes in parallel. base::FilePath output_file; - CHECK(CreateNewTempDirectory(FilePath::StringType(), &output_file)); - output_file = output_file.AppendASCII("test_results.xml"); + CHECK(platform_delegate_->CreateTemporaryFile(&output_file)); - CommandLine cmd_line( - GetCommandLineForChildGTestProcess(test_names, output_file)); + CommandLine cmd_line(platform_delegate_->GetCommandLineForChildGTestProcess( + test_names, output_file)); // Adjust the timeout depending on how many tests we're running // (note that e.g. the last batch of tests will be smaller). @@ -346,7 +376,9 @@ callback_state.output_file = output_file; test_launcher->LaunchChildGTestProcess( - cmd_line, std::string(), timeout, + cmd_line, + platform_delegate_->GetWrapperForChildGTestProcess(), + timeout, use_job_objects_ ? TestLauncher::USE_JOB_OBJECTS : 0, Bind(&UnitTestLauncherDelegate::GTestCallback, Unretained(this), callback_state));
diff --git a/base/test/launcher/unit_test_launcher.h b/base/test/launcher/unit_test_launcher.h index 0f661db..e4997a026 100644 --- a/base/test/launcher/unit_test_launcher.h +++ b/base/test/launcher/unit_test_launcher.h
@@ -33,10 +33,38 @@ const RunTestSuiteCallback& run_test_suite); #endif // defined(OS_WIN) +// Delegate to abstract away platform differences for unit tests. +class UnitTestPlatformDelegate { + public: + // Called to get names of tests available for running. The delegate + // must put the result in |output| and return true on success. + virtual bool GetTests(std::vector<SplitTestName>* output) = 0; + + // Called to create a temporary file. The delegate must put the resulting + // path in |path| and return true on success. + virtual bool CreateTemporaryFile(base::FilePath* path) = 0; + + // Returns command line for child GTest process based on the command line + // of current process. |test_names| is a vector of test full names + // (e.g. "A.B"), |output_file| is path to the GTest XML output file. + virtual CommandLine GetCommandLineForChildGTestProcess( + const std::vector<std::string>& test_names, + const base::FilePath& output_file) = 0; + + // Returns wrapper to use for child GTest process. Empty string means + // no wrapper. + virtual std::string GetWrapperForChildGTestProcess() = 0; + + protected: + ~UnitTestPlatformDelegate() {} +}; + // Test launcher delegate for unit tests (mostly to support batching). class UnitTestLauncherDelegate : public TestLauncherDelegate { public: - explicit UnitTestLauncherDelegate(size_t batch_limit, bool use_job_objects); + UnitTestLauncherDelegate(UnitTestPlatformDelegate* delegate, + size_t batch_limit, + bool use_job_objects); ~UnitTestLauncherDelegate() override; private: @@ -93,6 +121,8 @@ ThreadChecker thread_checker_; + UnitTestPlatformDelegate* platform_delegate_; + // Maximum number of tests to run in a single batch. size_t batch_limit_;
diff --git a/base/test/mock_time_provider.cc b/base/test/mock_time_provider.cc deleted file mode 100644 index 9e5547f..0000000 --- a/base/test/mock_time_provider.cc +++ /dev/null
@@ -1,31 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/logging.h" -#include "base/test/mock_time_provider.h" - -using ::testing::DefaultValue; - -namespace base { - -MockTimeProvider* MockTimeProvider::instance_ = NULL; - -MockTimeProvider::MockTimeProvider() { - DCHECK(!instance_) << "Only one instance of MockTimeProvider can exist"; - DCHECK(!DefaultValue<Time>::IsSet()); - instance_ = this; - DefaultValue<Time>::Set(Time::FromInternalValue(0)); -} - -MockTimeProvider::~MockTimeProvider() { - instance_ = NULL; - DefaultValue<Time>::Clear(); -} - -// static -Time MockTimeProvider::StaticNow() { - return instance_->Now(); -} - -} // namespace base
diff --git a/base/test/mock_time_provider.h b/base/test/mock_time_provider.h deleted file mode 100644 index 7c58648e..0000000 --- a/base/test/mock_time_provider.h +++ /dev/null
@@ -1,69 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// TODO(akalin): Change all users of this class to use SimpleTestClock -// or SimpleTestTickClock and remove this class. - -// A helper class used to mock out calls to the static method base::Time::Now. -// -// Example usage: -// -// typedef base::Time(TimeProvider)(); -// class StopWatch { -// public: -// StopWatch(TimeProvider* time_provider); -// void Start(); -// base::TimeDelta Stop(); -// private: -// TimeProvider* time_provider_; -// ... -// } -// -// Normally, you would instantiate a StopWatch with the real Now function: -// -// StopWatch watch(&base::Time::Now); -// -// But when testing, you want to instantiate it with -// MockTimeProvider::StaticNow, which calls an internally mocked out member. -// This allows you to set expectations on the Now method. For example: -// -// TEST_F(StopWatchTest, BasicTest) { -// InSequence s; -// StrictMock<MockTimeProvider> mock_time; -// EXPECT_CALL(mock_time, Now()) -// .WillOnce(Return(Time::FromDoubleT(4))); -// EXPECT_CALL(mock_time, Now()) -// .WillOnce(Return(Time::FromDoubleT(10))); -// -// StopWatch sw(&MockTimeProvider::StaticNow); -// sw.Start(); // First call to Now. -// TimeDelta elapsed = sw.stop(); // Second call to Now. -// ASSERT_EQ(elapsed, TimeDelta::FromSeconds(6)); -// } - -#ifndef BASE_TEST_MOCK_TIME_PROVIDER_H_ -#define BASE_TEST_MOCK_TIME_PROVIDER_H_ - -#include "base/time/time.h" -#include "testing/gmock/include/gmock/gmock.h" - -namespace base { - -class MockTimeProvider { - public: - MockTimeProvider(); - ~MockTimeProvider(); - - MOCK_METHOD0(Now, Time()); - - static Time StaticNow(); - - private: - static MockTimeProvider* instance_; - DISALLOW_COPY_AND_ASSIGN(MockTimeProvider); -}; - -} // namespace base - -#endif // BASE_TEST_MOCK_TIME_PROVIDER_H_
diff --git a/base/test/test_suite.cc b/base/test/test_suite.cc index a6fc201..903e93e 100644 --- a/base/test/test_suite.cc +++ b/base/test/test_suite.cc
@@ -171,7 +171,6 @@ listeners.Append(new TestClientInitializer); } -#if !defined(OS_IOS) void TestSuite::AddTestLauncherResultPrinter() { // Only add the custom printer if requested. if (!base::CommandLine::ForCurrentProcess()->HasSwitch( @@ -197,7 +196,6 @@ testing::UnitTest::GetInstance()->listeners(); listeners.Append(printer); } -#endif // !defined(OS_IOS) // Don't add additional code to this method. Instead add it to // Initialize(). See bug 6436. @@ -326,9 +324,7 @@ CatchMaybeTests(); ResetCommandLine(); -#if !defined(OS_IOS) AddTestLauncherResultPrinter(); -#endif // !defined(OS_IOS) TestTimeouts::Initialize();
diff --git a/base/test/trace_event_analyzer_unittest.cc b/base/test/trace_event_analyzer_unittest.cc index 0edeb14..cc1f8a3c 100644 --- a/base/test/trace_event_analyzer_unittest.cc +++ b/base/test/trace_event_analyzer_unittest.cc
@@ -3,9 +3,9 @@ // found in the LICENSE file. #include "base/bind.h" -#include "base/debug/trace_event_unittest.h" #include "base/synchronization/waitable_event.h" #include "base/test/trace_event_analyzer.h" +#include "base/threading/platform_thread.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -409,7 +409,7 @@ TRACE_EVENT_BEGIN0("cat2", "name3"); // found by duration query // next event not searched for, just noise TRACE_EVENT_INSTANT0("noise", "name4", TRACE_EVENT_SCOPE_THREAD); - base::debug::HighResSleepForTraceTest(kSleepTime); + base::PlatformThread::Sleep(kSleepTime); TRACE_EVENT_BEGIN0("cat2", "name5"); // not found (duration too short) TRACE_EVENT_END0("cat2", "name5"); // not found (duration too short) TRACE_EVENT_END0("cat2", "name3"); // found by duration query @@ -455,7 +455,7 @@ TRACE_EVENT0("cat2", "name3"); // found by duration query // next event not searched for, just noise TRACE_EVENT_INSTANT0("noise", "name4", TRACE_EVENT_SCOPE_THREAD); - base::debug::HighResSleepForTraceTest(kSleepTime); + base::PlatformThread::Sleep(kSleepTime); TRACE_EVENT0("cat2", "name5"); // not found (duration too short) } }
diff --git a/base/threading/thread_perftest.cc b/base/threading/thread_perftest.cc index 9fbc844..b94f942 100644 --- a/base/threading/thread_perftest.cc +++ b/base/threading/thread_perftest.cc
@@ -76,10 +76,10 @@ Init(); - base::TimeTicks start = base::TimeTicks::HighResNow(); + base::TimeTicks start = base::TimeTicks::Now(); PingPong(kNumRuns); done_.Wait(); - base::TimeTicks end = base::TimeTicks::HighResNow(); + base::TimeTicks end = base::TimeTicks::Now(); // Gather the cpu-time spent on each thread. This does one extra tasks, // but that should be in the noise given enough runs.
diff --git a/base/time/tick_clock.h b/base/time/tick_clock.h index 3e53d83..2b8691fa 100644 --- a/base/time/tick_clock.h +++ b/base/time/tick_clock.h
@@ -17,8 +17,8 @@ // See DefaultTickClock (base/time/default_tick_clock.h) for the default // implementation that simply uses TimeTicks::Now(). // -// (Other implementations that use TimeTicks::HighResNow() or -// TimeTicks::NowFromSystemTime() should be added as needed.) +// (Other implementations that use TimeTicks::NowFromSystemTime() should +// be added as needed.) // // See SimpleTestTickClock (base/test/simple_test_tick_clock.h) for a // simple test implementation.
diff --git a/base/time/time.h b/base/time/time.h index 915eac8f3..eb86693 100644 --- a/base/time/time.h +++ b/base/time/time.h
@@ -603,21 +603,12 @@ // microsecond. static TimeTicks Now(); - // DEPRECATED - // TODO(miu): Remove this function, and all callpoints should call Now(). - static TimeTicks HighResNow() { return TimeTicks::Now(); } - // Returns true if the high resolution clock is working on this system and // Now() will return high resolution values. Note that, on systems where the // high resolution clock works but is deemed inefficient, the low resolution // clock will be used instead. static bool IsHighResolution(); - // DEPRECATED - // TODO(miu): Remove this function, and all callpoints should call - // IsHighResolution(). - static bool IsHighResNowFastAndReliable() { return IsHighResolution(); } - // Returns true if ThreadNow() is supported on this system. static bool IsThreadNowSupported() { #if (defined(_POSIX_THREAD_CPUTIME) && (_POSIX_THREAD_CPUTIME >= 0)) || \
diff --git a/base/time/time_mac.cc b/base/time/time_mac.cc index 3944d06..e263d079 100644 --- a/base/time/time_mac.cc +++ b/base/time/time_mac.cc
@@ -230,7 +230,7 @@ // static TimeTicks TimeTicks::NowFromSystemTraceTime() { - return HighResNow(); + return Now(); } } // namespace base
diff --git a/base/time/time_posix.cc b/base/time/time_posix.cc index 34b2f5ac..8b207eb 100644 --- a/base/time/time_posix.cc +++ b/base/time/time_posix.cc
@@ -338,7 +338,7 @@ struct timespec ts; if (clock_gettime(kClockSystemTrace, &ts) != 0) { // NB: fall-back for a chrome os build running on linux - return HighResNow(); + return Now(); } absolute_micro = @@ -352,7 +352,7 @@ // static TimeTicks TimeTicks::NowFromSystemTraceTime() { - return HighResNow(); + return Now(); } #endif // defined(OS_CHROMEOS)
diff --git a/base/time/time_unittest.cc b/base/time/time_unittest.cc index 07b1e6b..27f71b4 100644 --- a/base/time/time_unittest.cc +++ b/base/time/time_unittest.cc
@@ -643,8 +643,8 @@ } static void HighResClockTest(TimeTicks (*GetTicks)()) { - // HighResNow doesn't work on some systems. Since the product still works - // even if it doesn't work, it makes this entire test questionable. + // IsHighResolution() is false on some systems. Since the product still works + // even if it's false, it makes this entire test questionable. if (!TimeTicks::IsHighResolution()) return; @@ -679,8 +679,8 @@ EXPECT_TRUE(success); } -TEST(TimeTicks, HighResNow) { - HighResClockTest(&TimeTicks::HighResNow); +TEST(TimeTicks, HighRes) { + HighResClockTest(&TimeTicks::Now); } // Fails frequently on Android http://crbug.com/352633 with: @@ -711,7 +711,7 @@ } TEST(TimeTicks, NowFromSystemTraceTime) { - // Re-use HighResNow test for now since clock properties are identical. + // Re-use HighRes test for now since clock properties are identical. HighResClockTest(&TimeTicks::NowFromSystemTraceTime); }
diff --git a/base/time/time_win_unittest.cc b/base/time/time_win_unittest.cc index 71cd29e..82be8c5 100644 --- a/base/time/time_win_unittest.cc +++ b/base/time/time_win_unittest.cc
@@ -116,8 +116,8 @@ } TEST(TimeTicks, SubMillisecondTimers) { - // HighResNow doesn't work on some systems. Since the product still works - // even if it doesn't work, it makes this entire test questionable. + // IsHighResolution() is false on some systems. Since the product still works + // even if it's false, it makes this entire test questionable. if (!TimeTicks::IsHighResolution()) return; @@ -126,11 +126,11 @@ // Run kRetries attempts to see a sub-millisecond timer. for (int index = 0; index < kRetries; index++) { - TimeTicks last_time = TimeTicks::HighResNow(); + TimeTicks last_time = TimeTicks::Now(); TimeDelta delta; // Spin until the clock has detected a change. do { - delta = TimeTicks::HighResNow() - last_time; + delta = TimeTicks::Now() - last_time; } while (delta.InMicroseconds() == 0); if (delta.InMicroseconds() < 1000) { saw_submillisecond_timer = true; @@ -193,10 +193,10 @@ int test_case = 0; while (cases[test_case].func) { - TimeTicks start = TimeTicks::HighResNow(); + TimeTicks start = TimeTicks::Now(); for (int index = 0; index < kLoops; index++) cases[test_case].func(); - TimeTicks stop = TimeTicks::HighResNow(); + TimeTicks stop = TimeTicks::Now(); // Turning off the check for acceptible delays. Without this check, // the test really doesn't do much other than measure. But the // measurements are still useful for testing timers on various platforms.
diff --git a/build/android/adb_gdb b/build/android/adb_gdb index ec0bb7e..150eb5eb 100755 --- a/build/android/adb_gdb +++ b/build/android/adb_gdb
@@ -841,7 +841,7 @@ if [ "$SU_PREFIX" ]; then # Need to check that this works properly. SU_PREFIX_TEST_LOG=$TMPDIR/su-prefix.log - adb_shell $SU_PREFIX echo "foo" > $SU_PREFIX_TEST_LOG 2>&1 + adb_shell $SU_PREFIX \"echo "foo"\" > $SU_PREFIX_TEST_LOG 2>&1 if [ $? != 0 -o "$(cat $SU_PREFIX_TEST_LOG)" != "foo" ]; then echo "ERROR: Cannot use '$SU_PREFIX' as a valid su prefix:" echo "$ adb shell $SU_PREFIX echo foo" @@ -867,7 +867,7 @@ if [ "$PULL_LIBS" -a -z "$NO_PULL_LIBS" ]; then echo "Extracting system libraries into: $PULL_LIBS_DIR" rm -f $PULL_LIBS_DIR/build.prop - MAPPINGS=$(adb_shell $COMMAND_PREFIX cat /proc/$PID/maps) + MAPPINGS=$(adb_shell $COMMAND_PREFIX \"cat /proc/$PID/maps\") if [ $? != 0 ]; then echo "ERROR: Could not list process's memory mappings." if [ "$SU_PREFIX" ]; then @@ -944,10 +944,10 @@ # log "Starting gdbserver in the background:" GDBSERVER_LOG=$TMPDIR/gdbserver-$TMP_ID.log -log "adb shell $COMMAND_PREFIX $TARGET_GDBSERVER :$TARGET_PORT \ ---attach $PID" -("$ADB" shell $COMMAND_PREFIX $TARGET_GDBSERVER :$TARGET_PORT \ - --attach $PID > $GDBSERVER_LOG 2>&1) & +log "adb shell $COMMAND_PREFIX \"$TARGET_GDBSERVER :$TARGET_PORT \ +--attach $PID"\" +("$ADB" shell $COMMAND_PREFIX \"$TARGET_GDBSERVER :$TARGET_PORT \ + --attach $PID\" > $GDBSERVER_LOG 2>&1) & GDBSERVER_PID=$! echo "$GDBSERVER_PID" > $GDBSERVER_PIDFILE log "background job pid: $GDBSERVER_PID"
diff --git a/build/android/provision_devices.py b/build/android/provision_devices.py index c719754..69258d4 100755 --- a/build/android/provision_devices.py +++ b/build/android/provision_devices.py
@@ -10,8 +10,8 @@ ./provision_devices.py [-d <device serial number>] """ +import argparse import logging -import optparse import os import re import subprocess @@ -79,7 +79,7 @@ '/data/local/tmp/adb_reboot') -def _ConfigureLocalProperties(device, is_perf): +def _ConfigureLocalProperties(device, java_debug=True): """Set standard readonly testing device properties prior to reboot.""" local_props = [ 'persist.sys.usb.config=adb', @@ -88,7 +88,7 @@ 'ro.audio.silent=1', 'ro.setupwizard.mode=DISABLED', ] - if not is_perf: + if java_debug: local_props.append('%s=all' % android_commands.JAVA_ASSERT_PROPERTY) local_props.append('debug.checkjni=1') try: @@ -97,7 +97,7 @@ '\n'.join(local_props), as_root=True) # Android will not respect the local props file if it is world writable. device.RunShellCommand( - 'chmod 644 %s' % constants.DEVICE_LOCAL_PROPERTIES_PATH, + ['chmod', '644', constants.DEVICE_LOCAL_PROPERTIES_PATH], as_root=True) except device_errors.CommandFailedError as e: logging.warning(str(e)) @@ -136,25 +136,24 @@ as_root=True) -def WipeDeviceIfPossible(device): +def WipeDeviceIfPossible(device, timeout): try: device.EnableRoot() WipeDeviceData(device) - # TODO(jbudorick): Tune the timeout per OS version. - device.Reboot(True, timeout=600, retries=0) + device.Reboot(True, timeout=timeout, retries=0) except (errors.DeviceUnresponsiveError, device_errors.CommandFailedError): pass -def ProvisionDevice(device, options, is_perf): +def ProvisionDevice(device, options): try: if not options.skip_wipe: - WipeDeviceIfPossible(device) + WipeDeviceIfPossible(device, options.reboot_timeout) try: device.EnableRoot() except device_errors.CommandFailedError as e: logging.warning(str(e)) - _ConfigureLocalProperties(device, is_perf) + _ConfigureLocalProperties(device, options.enable_java_debug) device_settings.ConfigureContentSettings( device, device_settings.DETERMINISTIC_DEVICE_SETTINGS) if options.disable_location: @@ -164,14 +163,10 @@ device_settings.ConfigureContentSettings( device, device_settings.ENABLE_LOCATION_SETTINGS) device_settings.SetLockScreenSettings(device) - if is_perf: - # TODO(tonyg): We eventually want network on. However, currently radios - # can cause perfbots to drain faster than they charge. + if options.disable_network: device_settings.ConfigureContentSettings( device, device_settings.NETWORK_DISABLED_SETTINGS) - # Some perf bots run benchmarks with USB charging disabled which leads - # to gradual draining of the battery. We must wait for a full charge - # before starting a run in order to keep the devices online. + if options.wait_for_battery: try: battery_info = device.old_interface.GetBatteryInfo() except Exception as e: @@ -191,8 +186,7 @@ time.sleep(60) battery_info = device.old_interface.GetBatteryInfo() if not options.skip_wipe: - # TODO(jbudorick): Tune the timeout per OS version. - device.Reboot(True, timeout=600, retries=0) + device.Reboot(True, timeout=options.reboot_timeout, retries=0) device.RunShellCommand('date -s %s' % time.strftime('%Y%m%d.%H%M%S', time.gmtime()), as_root=True) @@ -214,14 +208,13 @@ def ProvisionDevices(options): - is_perf = 'perf' in os.environ.get('BUILDBOT_BUILDERNAME', '').lower() if options.device is not None: devices = [options.device] else: devices = android_commands.GetAttachedDevices() parallel_devices = device_utils.DeviceUtils.parallel(devices) - parallel_devices.pMap(ProvisionDevice, options, is_perf) + parallel_devices.pMap(ProvisionDevice, options) if options.auto_reconnect: LaunchHostHeartbeat() blacklist = device_blacklist.ReadBlacklist() @@ -230,35 +223,70 @@ return 0 -def main(argv): +def main(): custom_handler = logging.StreamHandler(sys.stdout) custom_handler.setFormatter(run_tests_helper.CustomFormatter()) logging.getLogger().addHandler(custom_handler) logging.getLogger().setLevel(logging.INFO) - parser = optparse.OptionParser() - parser.add_option('--min-battery-level', default=95, type='int', - help="Minimum battery level for performance testing " - "(default: 95).") - parser.add_option('--skip-wipe', action='store_true', default=False, - help="Don't wipe device data during provisioning.") - parser.add_option('--disable-location', action='store_true', default=False, - help="Disallow Google location services on devices.") - parser.add_option('-d', '--device', - help='The serial number of the device to be provisioned') - parser.add_option('-t', '--target', default='Debug', help='The build target') - parser.add_option( - '-r', '--auto-reconnect', action='store_true', - help='Push binary which will reboot the device on adb disconnections.') - options, args = parser.parse_args(argv[1:]) - constants.SetBuildType(options.target) + # TODO(perezju): This script used to rely on the builder name to determine + # the desired device configuration for perf bots. To safely phase this out, + # we now: + # - expose these configuration settings as command line options + # - set default values for these options based on the builder name, thus + # matching the previous behaviour of the script on all bots. + # - explicitly adding these options on the perf bots will also maintain the + # script behaviour, namely: + # --wait-for-battery --disable-network --disable-java-debug + # - after all perf-bot recipes are updated, we can remove the following + # builder-name-sniffing code and replace |is_perf| with |False|. + is_perf = 'perf' in os.environ.get('BUILDBOT_BUILDERNAME', '').lower() - if args: - print >> sys.stderr, 'Unused args %s' % args - return 1 + # Recommended options on perf bots: + # --disable-network + # TODO(tonyg): We eventually want network on. However, currently radios + # can cause perfbots to drain faster than they charge. + # --wait-for-battery + # Some perf bots run benchmarks with USB charging disabled which leads + # to gradual draining of the battery. We must wait for a full charge + # before starting a run in order to keep the devices online. - return ProvisionDevices(options) + parser = argparse.ArgumentParser( + description='Provision Android devices with settings required for bots.') + parser.add_argument('-d', '--device', metavar='SERIAL', + help='the serial number of the device to be provisioned' + ' (the default is to provision all devices attached)') + parser.add_argument('--skip-wipe', action='store_true', default=False, + help="don't wipe device data during provisioning") + parser.add_argument('--reboot-timeout', default=600, type=int, + metavar='SECS', + help='when wiping the device, max number of seconds to' + ' wait after each reboot (default: %(default)s)') + parser.add_argument('--wait-for-battery', action='store_true', + default=is_perf, + help='wait for the battery on the devices to charge') + parser.add_argument('--min-battery-level', default=95, type=int, + metavar='NUM', + help='when waiting for battery, minimum battery level' + ' required to continue (default: %(default)s)') + parser.add_argument('--disable-location', action='store_true', + help='disable Google location services on devices') + parser.add_argument('--disable-network', action='store_true', + default=is_perf, + help='disable network access on devices') + parser.add_argument('--disable-java-debug', action='store_false', + dest='enable_java_debug', default=not is_perf, + help='disable Java property asserts and JNI checking') + parser.add_argument('-t', '--target', default='Debug', + help='the build target (default: %(default)s)') + parser.add_argument('-r', '--auto-reconnect', action='store_true', + help='push binary which will reboot the device on adb' + ' disconnections') + args = parser.parse_args() + constants.SetBuildType(args.target) + + return ProvisionDevices(args) if __name__ == '__main__': - sys.exit(main(sys.argv)) + sys.exit(main())
diff --git a/build/android/pylib/base/test_instance_factory.py b/build/android/pylib/base/test_instance_factory.py index 2ba469c3..7e7cb0c 100644 --- a/build/android/pylib/base/test_instance_factory.py +++ b/build/android/pylib/base/test_instance_factory.py
@@ -19,7 +19,6 @@ return instrumentation_test_instance.InstrumentationTestInstance( args, isolator.Isolator(constants.ISOLATE_DEPS_DIR), error_func) elif args.command == 'uirobot': - return uirobot_test_instance.UirobotTestInstance(args) - + return uirobot_test_instance.UirobotTestInstance(args, error_func) error_func('Unable to create %s test instance.' % args.command)
diff --git a/build/android/pylib/constants.py b/build/android/pylib/constants.py index d845c94..8027012 100644 --- a/build/android/pylib/constants.py +++ b/build/android/pylib/constants.py
@@ -211,6 +211,7 @@ VALID_ENVIRONMENTS = ['local', 'remote_device'] VALID_TEST_TYPES = ['gtest', 'instrumentation', 'junit', 'linker', 'monkey', 'perf', 'python', 'uiautomator', 'uirobot'] +VALID_DEVICE_TYPES = ['Android', 'iOS'] def GetBuildType():
diff --git a/build/android/pylib/device/device_utils.py b/build/android/pylib/device/device_utils.py index a4ddef1..fab3c5d 100644 --- a/build/android/pylib/device/device_utils.py +++ b/build/android/pylib/device/device_utils.py
@@ -91,6 +91,13 @@ return time.strftime('%Y%m%dT%H%M%S', time.localtime()) +def _JoinLines(lines): + # makes sure that the last line is also terminated, and is more memory + # efficient than first appending an end-line to each line and then joining + # all of them together. + return ''.join(s for line in lines for s in (line, '\n')) + + class DeviceUtils(object): _VALID_SHELL_VARIABLE = re.compile('^[a-zA-Z_][a-zA-Z0-9_]*$') @@ -883,7 +890,8 @@ self.adb.Pull(device_path, host_path) @decorators.WithTimeoutAndRetriesFromInstance() - def ReadFile(self, device_path, as_root=False, timeout=None, retries=None): + def ReadFile(self, device_path, as_root=False, + timeout=None, retries=None): """Reads the contents of a file from the device. Args: @@ -895,22 +903,17 @@ retries: number of retries Returns: - The contents of the file at |device_path| as a list of lines. + The contents of |device_path| as a string. Contents are intepreted using + universal newlines, so the caller will see them encoded as '\n'. Also, + all lines will be terminated. Raises: - CommandFailedError if the file can't be read. + AdbCommandFailedError if the file can't be read. CommandTimeoutError on timeout. DeviceUnreachableError on missing device. """ - # TODO(jbudorick) Evaluate whether we want to return a list of lines after - # the implementation switch, and if file not found should raise exception. - if as_root: - if not self.old_interface.CanAccessProtectedFileContents(): - raise device_errors.CommandFailedError( - 'Cannot read from %s with root privileges.' % device_path) - return self.old_interface.GetProtectedFileContents(device_path) - else: - return self.old_interface.GetFileContents(device_path) + return _JoinLines(self.RunShellCommand( + ['cat', device_path], as_root=as_root, check_return=True)) @decorators.WithTimeoutAndRetriesFromInstance() def WriteFile(self, device_path, contents, as_root=False, force_push=False,
diff --git a/build/android/pylib/device/device_utils_test.py b/build/android/pylib/device/device_utils_test.py index 72ab99c..e346bee 100755 --- a/build/android/pylib/device/device_utils_test.py +++ b/build/android/pylib/device/device_utils_test.py
@@ -1065,56 +1065,33 @@ '/test/file/host/path') -class DeviceUtilsReadFileTest(DeviceUtilsOldImplTest): +class DeviceUtilsReadFileTest(DeviceUtilsNewImplTest): def testReadFile_exists(self): - with self.assertCallsSequence([ - ("adb -s 0123456789abcdef shell " - "'cat \"/read/this/test/file\" 2>/dev/null'", - 'this is a test file')]): - self.assertEqual(['this is a test file'], + with self.assertCall( + self.call.adb.Shell('cat /read/this/test/file'), + 'this is a test file\r\n'): + self.assertEqual('this is a test file\n', self.device.ReadFile('/read/this/test/file')) def testReadFile_doesNotExist(self): + with self.assertCall( + self.call.adb.Shell('cat /this/file/does.not.exist'), + self.ShellError('/system/bin/sh: cat: /this/file/does.not.exist: ' + 'No such file or directory')): + with self.assertRaises(device_errors.AdbCommandFailedError): + self.device.ReadFile('/this/file/does.not.exist') + + def testReadFile_withSU(self): with self.assertCalls( - "adb -s 0123456789abcdef shell " - "'cat \"/this/file/does.not.exist\" 2>/dev/null'", - ''): - self.device.ReadFile('/this/file/does.not.exist') - - def testReadFile_asRoot_withRoot(self): - self.device.old_interface._privileged_command_runner = ( - self.device.old_interface.RunShellCommand) - self.device.old_interface._protected_file_access_method_initialized = True - with self.assertCallsSequence([ - ("adb -s 0123456789abcdef shell " - "'cat \"/this/file/must.be.read.by.root\" 2> /dev/null'", - 'this is a test file\nread by root')]): + (self.call.device.NeedsSU(), True), + (self.call.adb.Shell("su -c sh -c 'cat /this/file/can.be.read.with.su'"), + 'this is a test file\nread with su')): self.assertEqual( - ['this is a test file', 'read by root'], - self.device.ReadFile('/this/file/must.be.read.by.root', - as_root=True)) - - def testReadFile_asRoot_withSu(self): - self.device.old_interface._privileged_command_runner = ( - self.device.old_interface.RunShellCommandWithSU) - self.device.old_interface._protected_file_access_method_initialized = True - with self.assertCallsSequence([ - ("adb -s 0123456789abcdef shell " - "'su -c cat \"/this/file/can.be.read.with.su\" 2> /dev/null'", - 'this is a test file\nread with su')]): - self.assertEqual( - ['this is a test file', 'read with su'], + 'this is a test file\nread with su\n', self.device.ReadFile('/this/file/can.be.read.with.su', as_root=True)) - def testReadFile_asRoot_rejected(self): - self.device.old_interface._privileged_command_runner = None - self.device.old_interface._protected_file_access_method_initialized = True - with self.assertRaises(device_errors.CommandFailedError): - self.device.ReadFile('/this/file/cannot.be.read.by.user', - as_root=True) - class DeviceUtilsWriteFileTest(DeviceUtilsNewImplTest):
diff --git a/build/android/pylib/flag_changer.py b/build/android/pylib/flag_changer.py index c0bcadb..718bc397 100644 --- a/build/android/pylib/flag_changer.py +++ b/build/android/pylib/flag_changer.py
@@ -7,6 +7,8 @@ import pylib.android_commands import pylib.device.device_utils +from pylib.device import device_errors + class FlagChanger(object): """Changes the flags Chrome runs with. @@ -32,9 +34,10 @@ self._cmdline_file = cmdline_file # Save the original flags. - self._orig_line = self._device.ReadFile(self._cmdline_file) - if self._orig_line: - self._orig_line = self._orig_line[0].strip() + try: + self._orig_line = self._device.ReadFile(self._cmdline_file).strip() + except device_errors.CommandFailedError: + self._orig_line = '' # Parse out the flags into a list to facilitate adding and removing flags. self._current_flags = self._TokenizeFlags(self._orig_line) @@ -104,8 +107,8 @@ self._device.WriteFile( self._cmdline_file, cmd_line, as_root=use_root) file_contents = self._device.ReadFile( - self._cmdline_file, as_root=use_root) - assert len(file_contents) == 1 and file_contents[0] == cmd_line, ( + self._cmdline_file, as_root=use_root).rstrip() + assert file_contents == cmd_line, ( 'Failed to set the command line file at %s' % self._cmdline_file) else: self._device.RunShellCommand('rm ' + self._cmdline_file,
diff --git a/build/android/pylib/instrumentation/test_runner.py b/build/android/pylib/instrumentation/test_runner.py index ec0baee..424dcb3 100644 --- a/build/android/pylib/instrumentation/test_runner.py +++ b/build/android/pylib/instrumentation/test_runner.py
@@ -237,10 +237,8 @@ '/data/data/com.google.android.apps.chrome/files/PerfTestData.txt', as_root=True) - if json_string: - json_string = '\n'.join(json_string) - else: - raise Exception('Perf file does not exist or is empty') + if not json_string: + raise Exception('Perf file is empty') if self.options.save_perf_json: json_local_file = '/tmp/chromium-android-perf-json-' + raw_test_name
diff --git a/build/android/pylib/perf/thermal_throttle.py b/build/android/pylib/perf/thermal_throttle.py index 24e1ff4c..383b6d5 100644 --- a/build/android/pylib/perf/thermal_throttle.py +++ b/build/android/pylib/perf/thermal_throttle.py
@@ -34,7 +34,7 @@ def GetCurrentTemperature(self): tempdata = self._device.ReadFile(OmapThrottlingDetector.OMAP_TEMP_FILE) - return float(tempdata[0]) / 1000.0 + return float(tempdata) / 1000.0 class ExynosThrottlingDetector(object):
diff --git a/build/android/pylib/remote/device/remote_device_environment.py b/build/android/pylib/remote/device/remote_device_environment.py index 3fdc716..a701d95 100644 --- a/build/android/pylib/remote/device/remote_device_environment.py +++ b/build/android/pylib/remote/device/remote_device_environment.py
@@ -65,6 +65,7 @@ self._runner_type = args.runner_type self._device = '' self._verbose_count = args.verbose_count + self._device_type = args.device_type self._timeouts = { 'queueing': 60 * 10, 'installing': 60 * 10, @@ -147,7 +148,7 @@ device_list = dev_list_res.json()['response'] random.shuffle(device_list) for device in device_list: - if device['os_name'] != 'Android': + if device['os_name'] != self._device_type: continue if self._remote_device and device['name'] != self._remote_device: continue @@ -169,9 +170,9 @@ return c return 0 - logging.critical('Available Android Devices:') - android_devices = (d for d in device_list if d['os_name'] == 'Android') - for d in sorted(android_devices, compare_devices): + logging.critical('Available %s Devices:', self._device_type) + devices = (d for d in device_list if d['os_name'] == self._device_type) + for d in sorted(devices, compare_devices): logging.critical(' %s %s', d['os_version'].ljust(7), d['name']) def _NoDeviceFound(self, device_list): @@ -218,3 +219,7 @@ @property def verbose_count(self): return self._verbose_count + + @property + def device_type(self): + return self._device_type
diff --git a/build/android/pylib/remote/device/remote_device_test_run.py b/build/android/pylib/remote/device/remote_device_test_run.py index c4f75b01..0b2deae 100644 --- a/build/android/pylib/remote/device/remote_device_test_run.py +++ b/build/android/pylib/remote/device/remote_device_test_run.py
@@ -19,7 +19,7 @@ from pylib.utils import zip_utils class RemoteDeviceTestRun(test_run.TestRun): - """Run gtests and uirobot tests on a remote device.""" + """Run tests on a remote device.""" _TEST_RUN_KEY = 'test_run' _TEST_RUN_ID_KEY = 'test_run_id'
diff --git a/build/android/pylib/remote/device/remote_device_uirobot_test_run.py b/build/android/pylib/remote/device/remote_device_uirobot_test_run.py index 7eedaa5..936db0a 100644 --- a/build/android/pylib/remote/device/remote_device_uirobot_test_run.py +++ b/build/android/pylib/remote/device/remote_device_uirobot_test_run.py
@@ -18,7 +18,6 @@ class RemoteDeviceUirobotTestRun(remote_device_test_run.RemoteDeviceTestRun): """Run uirobot tests on a remote device.""" - DEFAULT_RUNNER_TYPE = 'android_robot' def __init__(self, env, test_instance): """Constructor. @@ -37,16 +36,46 @@ def _TriggerSetUp(self): """Set up the triggering of a test run.""" logging.info('Triggering test run.') - self._app_id = self._UploadAppToDevice(self._test_instance.apk_under_test) + + if self._env.device_type == 'Android': + default_runner_type = 'android_robot' + elif self._env.device_type == 'iOS': + default_runner_type = 'ios_robot' + else: + raise remote_device_helper.RemoteDeviceError( + 'Unkown device type: %s' % self._env.device_type) + + self._app_id = self._UploadAppToDevice(self._test_instance.app_under_test) if not self._env.runner_type: - runner_type = self.DEFAULT_RUNNER_TYPE - logging.info('Using default runner type: %s', self.DEFAULT_RUNNER_TYPE) + runner_type = default_runner_type + logging.info('Using default runner type: %s', default_runner_type) else: runner_type = self._env.runner_type - self._test_id = self._GetTestByName(runner_type) + + self._test_id = self._UploadTestToDevice( + 'android_robot', None, app_id=self._app_id) config_body = {'duration': self._test_instance.minutes} self._SetTestConfig(runner_type, config_body) + + # TODO(rnephew): Switch to base class implementation when supported. + #override + def _UploadTestToDevice(self, test_type, test_path, app_id=None): + if test_path: + logging.info("Ignoring test path.") + data = { + 'access_token':self._env.token, + 'test_type':test_type, + 'app_id':app_id, + } + with appurify_sanitized.SanitizeLogging(self._env.verbose_count, + logging.WARNING): + test_upload_res = appurify_sanitized.utils.post('tests/upload', + data, None) + remote_device_helper.TestHttpResponse( + test_upload_res, 'Unable to get UiRobot test id.') + return test_upload_res.json()['response']['test_id'] + #override def _ParseTestResults(self): logging.info('Parsing results from remote service.')
diff --git a/build/android/pylib/uirobot/uirobot_test_instance.py b/build/android/pylib/uirobot/uirobot_test_instance.py index edd3200be..f73c569e6 100644 --- a/build/android/pylib/uirobot/uirobot_test_instance.py +++ b/build/android/pylib/uirobot/uirobot_test_instance.py
@@ -10,18 +10,26 @@ class UirobotTestInstance(test_instance.TestInstance): - def __init__(self, args): + def __init__(self, args, error_func): """Constructor. Args: args: Command line arguments. """ super(UirobotTestInstance, self).__init__() - self._apk_under_test = os.path.join( - constants.GetOutDirectory(), args.app_under_test) + if not args.app_under_test: + error_func('Must set --app-under-test.') + self._app_under_test = args.app_under_test + + if args.device_type == 'Android': + self._suite = 'Android Uirobot' + self._package_name = apk_helper.GetPackageName(self._app_under_test) + + elif args.device_type == 'iOS': + self._suite = 'iOS Uirobot' + self._package_name = self._app_under_test + self._minutes = args.minutes - self._package_name = apk_helper.GetPackageName(self._apk_under_test) - self._suite = 'Android Uirobot' #override def TestType(self): @@ -39,9 +47,9 @@ pass @property - def apk_under_test(self): + def app_under_test(self): """Returns the app to run the test on.""" - return self._apk_under_test + return self._app_under_test @property def minutes(self):
diff --git a/build/android/pylib/utils/logging_utils.py b/build/android/pylib/utils/logging_utils.py new file mode 100644 index 0000000..1e46fa8 --- /dev/null +++ b/build/android/pylib/utils/logging_utils.py
@@ -0,0 +1,27 @@ +# 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. + +import contextlib +import logging + +@contextlib.contextmanager +def SuppressLogging(level=logging.ERROR): + """Momentarilly suppress logging events from all loggers. + + TODO(jbudorick): This is not thread safe. Log events from other threads might + also inadvertently dissapear. + + Example: + + with logging_utils.SuppressLogging(): + # all but CRITICAL logging messages are suppressed + logging.info('just doing some thing') # not shown + logging.critical('something really bad happened') # still shown + + Args: + level: logging events with this or lower levels are suppressed. + """ + logging.disable(level) + yield + logging.disable(logging.NOTSET)
diff --git a/build/android/pylib/valgrind_tools.py b/build/android/pylib/valgrind_tools.py index 46cf9e3..99719d0811 100644 --- a/build/android/pylib/valgrind_tools.py +++ b/build/android/pylib/valgrind_tools.py
@@ -116,11 +116,13 @@ 'lib/clang/*/lib/linux/', 'libclang_rt.asan-arm-android.so')) assert len(libs) == 1 - subprocess.call([os.path.join(DIR_SOURCE_ROOT, - 'tools/android/asan/asan_device_setup.sh'), - '--device', str(device), - '--lib', libs[0], - '--extra-options', AddressSanitizerTool.EXTRA_OPTIONS]) + subprocess.call( + [os.path.join( + DIR_SOURCE_ROOT, + 'tools/android/asan/third_party/asan_device_setup.sh'), + '--device', str(device), + '--lib', libs[0], + '--extra-options', AddressSanitizerTool.EXTRA_OPTIONS]) device.WaitUntilFullyBooted() def GetTestWrapper(self):
diff --git a/build/android/test_runner.py b/build/android/test_runner.py index 4164bd8b..6eb368a 100755 --- a/build/android/test_runner.py +++ b/build/android/test_runner.py
@@ -102,7 +102,6 @@ help='If set, will dump results in JSON form ' 'to specified file.') - def ProcessCommonOptions(args): """Processes and handles all common options.""" run_tests_helper.SetLogLevel(args.verbose_count) @@ -140,10 +139,10 @@ group.add_argument('--api-port', help='Port to send HTTP requests to.') group.add_argument('--runner-type', default='', help='Type of test to run as.') - group.add_argument('--runner-package', default='', - help='Package name of test.') - group.add_argument('--app-under-test', default='', - help='APK to run tests on.') + group.add_argument('--runner-package', help='Package name of test.') + group.add_argument('--device-type', default='Android', + choices=constants.VALID_DEVICE_TYPES, + help=('Type of device to run on. iOS or android')) api_secret_group = group.add_mutually_exclusive_group() api_secret_group.add_argument('--api-secret', default='', @@ -507,6 +506,7 @@ """Adds uirobot test options to |option_parser|.""" group = parser.add_argument_group('Uirobot Test Options') + group.add_argument('--app-under-test', help='APK to run tests on.') group.add_argument( '--minutes', default=5, type=int, help='Number of minutes to run uirobot test [default: %default].')
diff --git a/build/android/tombstones.py b/build/android/tombstones.py index a78d89f..7449a73 100755 --- a/build/android/tombstones.py +++ b/build/android/tombstones.py
@@ -63,7 +63,8 @@ Returns: A list of lines """ - return device.ReadFile('/data/tombstones/' + tombstone_file, as_root=True) + return device.ReadFile( + '/data/tombstones/' + tombstone_file, as_root=True).splitlines() def _EraseTombstone(device, tombstone_file):
diff --git a/build/common.gypi b/build/common.gypi index dd0f6e9..1c33276 100644 --- a/build/common.gypi +++ b/build/common.gypi
@@ -2143,7 +2143,7 @@ 'conditions': [ # TODO(dcheng): https://crbug.com/417463 -- work to enable this flag # on all platforms is currently underway. - ['(OS=="linux" and chromeos==0) or OS=="mac" or OS=="ios"', { + ['(OS=="linux" and (chromeos==0 or use_ozone==0)) or OS=="mac" or OS=="ios"', { 'clang_chrome_plugins_flags': [ '-Xclang', '-plugin-arg-find-bad-constructs', @@ -5159,6 +5159,9 @@ }, # target_defaults }], # OS=="mac" ['OS=="ios"', { + 'includes': [ + 'ios/coverage.gypi', + ], 'target_defaults': { 'xcode_settings' : { 'CLANG_CXX_LANGUAGE_STANDARD': 'c++11', @@ -5549,52 +5552,6 @@ ], }, }], - ['asan==1', { - # ASan on Windows is a work in progress and very experimental. - # See crbug.com/345874. - 'VCCLCompilerTool': { - 'AdditionalOptions': [ - '-fsanitize=address', - ], - 'AdditionalIncludeDirectories': [ - # MSVC needs to be able to find the sanitizer headers when - # invoked via /fallback. This is critical for using macros - # like ASAN_UNPOISON_MEMORY_REGION in files where we fall - # back. - '<(DEPTH)/<(make_clang_dir)/lib/clang/3.7.0/include_sanitizer', - ], - }, - 'VCLinkerTool': { - 'AdditionalLibraryDirectories': [ - # TODO(hans): If make_clang_dir is absolute, this breaks. - '<(DEPTH)/<(make_clang_dir)/lib/clang/3.7.0/lib/windows', - ], - }, - 'target_conditions': [ - ['component=="shared_library"', { - 'VCLinkerTool': { - 'AdditionalDependencies': [ - 'clang_rt.asan_dynamic-i386.lib', - 'clang_rt.asan_dynamic_runtime_thunk-i386.lib', - ], - }, - }], - ['_type=="executable" and component=="static_library"', { - 'VCLinkerTool': { - 'AdditionalDependencies': [ - 'clang_rt.asan-i386.lib', - ], - }, - }], - ['(_type=="shared_library" or _type=="loadable_module") and component=="static_library"', { - 'VCLinkerTool': { - 'AdditionalDependencies': [ - 'clang_rt.asan_dll_thunk-i386.lib', - ], - }, - }], - ], - }], ], }, }, @@ -5629,12 +5586,61 @@ '/ignore:4221', '/nxcompat', ], - 'conditions': [ - ['syzyasan==0', { - 'AdditionalOptions': ['/largeaddressaware'], - }], - ], }, + 'conditions': [ + ['syzyasan==0', { + 'VCLinkerTool': { + 'AdditionalOptions': ['/largeaddressaware'], + }, + }], + ['asan==1', { + # TODO(asan/win): Move this down into the general + # win-target_defaults section once the 64-bit asan runtime + # exists. See crbug.com/345874. + 'VCCLCompilerTool': { + 'AdditionalOptions': [ + '-fsanitize=address', + ], + 'AdditionalIncludeDirectories': [ + # MSVC needs to be able to find the sanitizer headers when + # invoked via /fallback. This is critical for using macros + # like ASAN_UNPOISON_MEMORY_REGION in files where we fall + # back. + '<(DEPTH)/<(make_clang_dir)/lib/clang/3.7.0/include_sanitizer', + ], + }, + 'VCLinkerTool': { + 'AdditionalLibraryDirectories': [ + # TODO(hans): If make_clang_dir is absolute, this breaks. + '<(DEPTH)/<(make_clang_dir)/lib/clang/3.7.0/lib/windows', + ], + }, + 'target_conditions': [ + ['component=="shared_library"', { + 'VCLinkerTool': { + 'AdditionalDependencies': [ + 'clang_rt.asan_dynamic-i386.lib', + 'clang_rt.asan_dynamic_runtime_thunk-i386.lib', + ], + }, + }], + ['_type=="executable" and component=="static_library"', { + 'VCLinkerTool': { + 'AdditionalDependencies': [ + 'clang_rt.asan-i386.lib', + ], + }, + }], + ['(_type=="shared_library" or _type=="loadable_module") and component=="static_library"', { + 'VCLinkerTool': { + 'AdditionalDependencies': [ + 'clang_rt.asan_dll_thunk-i386.lib', + ], + }, + }], + ], + }], + ], }, }, 'x64_Base': {
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni index 4778705..125aa2cd 100644 --- a/build/config/android/internal_rules.gni +++ b/build/config/android/internal_rules.gni
@@ -273,6 +273,7 @@ if (is_apk) { if (defined(invoker.native_libs)) { + inputs += invoker.native_libs rebased_native_libs = rebase_path(invoker.native_libs, root_build_dir) rebased_android_readelf = rebase_path(android_readelf, root_build_dir) args += [
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni index 07431d7..cfc64954 100644 --- a/build/config/android/rules.gni +++ b/build/config/android/rules.gni
@@ -1341,9 +1341,7 @@ outputs = [ depfile, ] - inputs = [ - _build_config, - ] + inputs = [ _build_config ] + _native_libs deps = [] skip_packing_list = [ "gdbserver",
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn index cc2b7f5..ff518d97 100644 --- a/build/config/compiler/BUILD.gn +++ b/build/config/compiler/BUILD.gn
@@ -350,10 +350,7 @@ "-Wl,-z,now", "-Wl,-z,relro", ] - - # TODO(zork): The mipsel build is broken in ffmpeg, guard this flag for now - # to hide the breakage. https://crbug.com/450771 - if (!using_sanitizer && cpu_arch != "mipsel") { + if (!using_sanitizer) { ldflags += [ "-Wl,-z,defs" ] } } @@ -903,7 +900,17 @@ "/Oy-", # disable omitting frame pointers, must be after /o2. "/Os", # favor size over speed. ] - common_optimize_on_ldflags = [] + if (!is_asan) { + common_optimize_on_cflags += [ + # Put data in separate COMDATs. This allows the linker + # to put bit-identical constants at the same address even if + # they're unrelated constants, which saves binary size. + # This optimization can't be used when ASan is enabled because + # it is not compatible with the ASan ODR checker. + "/Gw", + ] + } + common_optimize_on_ldflags = [ "/OPT:REF" ] } else { common_optimize_on_cflags = [ # Don't emit the GCC version ident directives, they just end up in the
diff --git a/build/ios/coverage.gypi b/build/ios/coverage.gypi index afd3cdc..e822089 100644 --- a/build/ios/coverage.gypi +++ b/build/ios/coverage.gypi
@@ -4,11 +4,10 @@ { 'variables': { - 'chromium_code': 1, 'enable_coverage%': 0, }, 'conditions': [ - ['OS=="ios" and enable_coverage', { + ['enable_coverage', { 'target_defaults': { 'defines': [ 'ENABLE_TEST_CODE_COVERAGE=1'
diff --git a/build/ios/grit_whitelist.txt b/build/ios/grit_whitelist.txt index f8cbd8f..7fc4e1d1 100644 --- a/build/ios/grit_whitelist.txt +++ b/build/ios/grit_whitelist.txt
@@ -567,8 +567,6 @@ IDS_FLAGS_FORCE_HIGH_DPI_NAME IDS_FLAGS_IGNORE_GPU_BLACKLIST_DESCRIPTION IDS_FLAGS_IGNORE_GPU_BLACKLIST_NAME -IDS_FLAGS_IMPL_SIDE_PAINTING_DESCRIPTION -IDS_FLAGS_IMPL_SIDE_PAINTING_NAME IDS_FLAGS_LONG_TITLE IDS_FLAGS_NACL_DEBUG_MASK_DESCRIPTION IDS_FLAGS_NACL_DEBUG_MASK_NAME
diff --git a/build/secondary/tools/grit/grit_rule.gni b/build/secondary/tools/grit/grit_rule.gni index 7a1cc26..9d8d604 100644 --- a/build/secondary/tools/grit/grit_rule.gni +++ b/build/secondary/tools/grit/grit_rule.gni
@@ -54,6 +54,7 @@ # If set, output_dir is not added to include_dirs. # # deps (optional) +# data_deps (optional) # visibility (optional) # Normal meaning. # @@ -413,6 +414,9 @@ if (defined(invoker.deps)) { deps += invoker.deps } + if (defined(invoker.data_deps)) { + data_deps = invoker.data_deps + } } # This is the thing that people actually link with, it must be named the
diff --git a/cc/BUILD.gn b/cc/BUILD.gn index c3d77177b..a5945fb 100644 --- a/cc/BUILD.gn +++ b/cc/BUILD.gn
@@ -80,6 +80,8 @@ "debug/devtools_instrumentation.h", "debug/frame_rate_counter.cc", "debug/frame_rate_counter.h", + "debug/frame_timing_request.cc", + "debug/frame_timing_request.h", "debug/frame_timing_tracker.cc", "debug/frame_timing_tracker.h", "debug/frame_viewer_instrumentation.cc", @@ -401,6 +403,10 @@ "resources/raster_source.h", "resources/raster_source_helper.cc", "resources/raster_source_helper.h", + "resources/raster_tile_priority_queue_all.cc", + "resources/raster_tile_priority_queue_all.h", + "resources/raster_tile_priority_queue_required.cc", + "resources/raster_tile_priority_queue_required.h", "resources/raster_tile_priority_queue.cc", "resources/raster_tile_priority_queue.h", "resources/rasterizer.h", @@ -463,7 +469,6 @@ "resources/tiling_set_raster_queue_all.h", "resources/tiling_set_raster_queue_required.cc", "resources/tiling_set_raster_queue_required.h", - "resources/tiling_set_raster_queue.h", "resources/transferable_resource.cc", "resources/transferable_resource.h", "resources/transform_display_item.cc",
diff --git a/cc/blink/web_content_layer_impl.cc b/cc/blink/web_content_layer_impl.cc index 5bd3667a..abe3eb30 100644 --- a/cc/blink/web_content_layer_impl.cc +++ b/cc/blink/web_content_layer_impl.cc
@@ -54,11 +54,8 @@ if (!client_) return; - // TODO(danakj): Stop passing this to blink it should always use LCD when it - // wants to. crbug.com/430617 - bool can_use_lcd_text = true; client_->paintContents( - canvas, clip, can_use_lcd_text, + canvas, clip, graphics_context_status == ContentLayerClient::GRAPHICS_CONTEXT_ENABLED ? blink::WebContentLayerClient::GraphicsContextEnabled : blink::WebContentLayerClient::GraphicsContextDisabled); @@ -72,9 +69,8 @@ return cc::DisplayItemList::Create(); WebDisplayItemListImpl list; - bool can_use_lcd_text = true; client_->paintContents( - &list, clip, can_use_lcd_text, + &list, clip, graphics_context_status == ContentLayerClient::GRAPHICS_CONTEXT_ENABLED ? blink::WebContentLayerClient::GraphicsContextEnabled : blink::WebContentLayerClient::GraphicsContextDisabled);
diff --git a/cc/cc.gyp b/cc/cc.gyp index 69d1907..49d2f64de 100644 --- a/cc/cc.gyp +++ b/cc/cc.gyp
@@ -106,6 +106,8 @@ 'debug/devtools_instrumentation.h', 'debug/frame_rate_counter.cc', 'debug/frame_rate_counter.h', + 'debug/frame_timing_request.cc', + 'debug/frame_timing_request.h', 'debug/frame_timing_tracker.cc', 'debug/frame_timing_tracker.h', 'debug/frame_viewer_instrumentation.cc', @@ -427,6 +429,10 @@ 'resources/raster_source.h', 'resources/raster_source_helper.cc', 'resources/raster_source_helper.h', + 'resources/raster_tile_priority_queue_all.cc', + 'resources/raster_tile_priority_queue_all.h', + 'resources/raster_tile_priority_queue_required.cc', + 'resources/raster_tile_priority_queue_required.h', 'resources/raster_tile_priority_queue.cc', 'resources/raster_tile_priority_queue.h', 'resources/rasterizer.h', @@ -490,7 +496,6 @@ 'resources/tiling_set_raster_queue_all.h', 'resources/tiling_set_raster_queue_required.cc', 'resources/tiling_set_raster_queue_required.h', - 'resources/tiling_set_raster_queue.h', 'resources/transferable_resource.cc', 'resources/transferable_resource.h', 'resources/transform_display_item.cc',
diff --git a/cc/debug/frame_timing_request.cc b/cc/debug/frame_timing_request.cc new file mode 100644 index 0000000..6c54ea28 --- /dev/null +++ b/cc/debug/frame_timing_request.cc
@@ -0,0 +1,17 @@ +// Copyright 2015 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 "cc/debug/frame_timing_request.h" + +namespace cc { + +FrameTimingRequest::FrameTimingRequest() : id_(0) { +} + +FrameTimingRequest::FrameTimingRequest(int64_t request_id, + const gfx::Rect& rect) + : id_(request_id), rect_(rect) { +} + +} // namespace cc
diff --git a/cc/debug/frame_timing_request.h b/cc/debug/frame_timing_request.h new file mode 100644 index 0000000..7ab97de --- /dev/null +++ b/cc/debug/frame_timing_request.h
@@ -0,0 +1,31 @@ +// Copyright 2015 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 CC_DEBUG_FRAME_TIMING_REQUEST_H_ +#define CC_DEBUG_FRAME_TIMING_REQUEST_H_ + +#include "ui/gfx/geometry/rect.h" + +namespace cc { + +// This class represents a request to record frame timing information about the +// given rect (in layer space) and an associated request id. When this request +// is propagated to the active LayerImpl, it will cause events to be saved in +// FrameTimingTracker, which in turn can be consumed by the requester. +class FrameTimingRequest { + public: + FrameTimingRequest(); + FrameTimingRequest(int64_t request_id, const gfx::Rect& rect); + + int64_t id() const { return id_; } + const gfx::Rect& rect() const { return rect_; } + + private: + int64_t id_; + gfx::Rect rect_; +}; + +} // namespace cc + +#endif // CC_DEBUG_FRAME_TIMING_REQUEST_H_
diff --git a/cc/debug/lap_timer.cc b/cc/debug/lap_timer.cc index 27aaf34..10d26f94 100644 --- a/cc/debug/lap_timer.cc +++ b/cc/debug/lap_timer.cc
@@ -11,9 +11,8 @@ namespace { base::TimeTicks Now() { - return base::TimeTicks::IsThreadNowSupported() - ? base::TimeTicks::ThreadNow() - : base::TimeTicks::HighResNow(); + return base::TimeTicks::IsThreadNowSupported() ? base::TimeTicks::ThreadNow() + : base::TimeTicks::Now(); } } // namespace
diff --git a/cc/debug/picture_record_benchmark.cc b/cc/debug/picture_record_benchmark.cc index cc01448f..d0d031d 100644 --- a/cc/debug/picture_record_benchmark.cc +++ b/cc/debug/picture_record_benchmark.cc
@@ -104,12 +104,12 @@ for (int x = 0; x < x_limit; x += kPositionIncrement) { gfx::Rect rect = gfx::Rect(x, y, width, height); - base::TimeTicks start = base::TimeTicks::HighResNow(); + base::TimeTicks start = base::TimeTicks::Now(); scoped_refptr<Picture> picture = Picture::Create( rect, painter, tile_grid_size, false, Picture::RECORD_NORMALLY); - base::TimeTicks end = base::TimeTicks::HighResNow(); + base::TimeTicks end = base::TimeTicks::Now(); base::TimeDelta duration = end - start; TotalTime& total_time = times_[dimensions]; total_time.first += duration;
diff --git a/cc/debug/rendering_stats_instrumentation.cc b/cc/debug/rendering_stats_instrumentation.cc index c707e23..4a28a66 100644 --- a/cc/debug/rendering_stats_instrumentation.cc +++ b/cc/debug/rendering_stats_instrumentation.cc
@@ -41,7 +41,7 @@ if (record_rendering_stats_) { if (base::TimeTicks::IsThreadNowSupported()) return base::TimeTicks::ThreadNow(); - return base::TimeTicks::HighResNow(); + return base::TimeTicks::Now(); } return base::TimeTicks(); } @@ -51,7 +51,7 @@ if (!start_time.is_null()) { if (base::TimeTicks::IsThreadNowSupported()) return base::TimeTicks::ThreadNow() - start_time; - return base::TimeTicks::HighResNow() - start_time; + return base::TimeTicks::Now() - start_time; } return base::TimeDelta(); }
diff --git a/cc/layers/delegated_renderer_layer_impl_unittest.cc b/cc/layers/delegated_renderer_layer_impl_unittest.cc index 395d3619..aaef9f2 100644 --- a/cc/layers/delegated_renderer_layer_impl_unittest.cc +++ b/cc/layers/delegated_renderer_layer_impl_unittest.cc
@@ -769,9 +769,9 @@ &root_delegated_shared_quad_state, &contrib_delegated_shared_quad_state); - // When the layer owns a surface, then its position and translation are not - // a part of its draw transform. - EXPECT_EQ(gfx::Rect(10, 10, 35, 35).ToString(), + // When the layer owns a surface, then its translation is not part of its + // draw transform, but its scale is. + EXPECT_EQ(gfx::Rect(20, 20, 70, 70).ToString(), root_delegated_shared_quad_state->clip_rect.ToString()); // Since the layer owns a surface it doesn't need to clip its quads, so @@ -779,8 +779,9 @@ EXPECT_FALSE(root_delegated_shared_quad_state->is_clipped); gfx::Transform expected; - // This is the transform within the source frame. - expected.Scale(1.5, 1.5); + // This is the transform within the source frame scaled by the delegated + // render layer transform. + expected.Scale(3.0, 3.0); expected.Translate(7.0, 7.0); EXPECT_TRANSFORMATION_MATRIX_EQ( expected, root_delegated_shared_quad_state->content_to_target_transform); @@ -817,17 +818,18 @@ &root_delegated_shared_quad_state, &contrib_delegated_shared_quad_state); - // When the layer owns a surface, then its position and translation are not - // a part of its draw transform. The clip_rect should be preserved. - EXPECT_EQ(gfx::Rect(10, 10, 35, 35).ToString(), + // When the layer owns a surface, then its translation is not part of its + // draw transform, but its scale is. + EXPECT_EQ(gfx::Rect(20, 20, 70, 70).ToString(), root_delegated_shared_quad_state->clip_rect.ToString()); // The quads had a clip and it should be preserved. EXPECT_TRUE(root_delegated_shared_quad_state->is_clipped); gfx::Transform expected; - // This is the transform within the source frame. - expected.Scale(1.5, 1.5); + // This is the transform within the source frame scaled by the delegated + // render layer transform. + expected.Scale(3.0, 3.0); expected.Translate(7.0, 7.0); EXPECT_TRANSFORMATION_MATRIX_EQ( expected, root_delegated_shared_quad_state->content_to_target_transform);
diff --git a/cc/layers/layer.cc b/cc/layers/layer.cc index 45e8a83..feb23fa 100644 --- a/cc/layers/layer.cc +++ b/cc/layers/layer.cc
@@ -78,7 +78,8 @@ clip_parent_(nullptr), replica_layer_(nullptr), raster_scale_(0.f), - client_(nullptr) { + client_(nullptr), + frame_timing_requests_dirty_(false) { layer_animation_controller_ = LayerAnimationController::Create(layer_id_); layer_animation_controller_->AddValueObserver(this); layer_animation_controller_->set_value_provider(this); @@ -1013,6 +1014,11 @@ layer_animation_controller_->PushAnimationUpdatesTo( layer->layer_animation_controller()); + if (frame_timing_requests_dirty_) { + layer->PassFrameTimingRequests(&frame_timing_requests_); + frame_timing_requests_dirty_ = false; + } + // Reset any state that should be cleared for the next update. stacking_order_changed_ = false; update_rect_ = gfx::Rect(); @@ -1287,4 +1293,11 @@ return xform; } +void Layer::SetFrameTimingRequests( + const std::vector<FrameTimingRequest>& requests) { + frame_timing_requests_ = requests; + frame_timing_requests_dirty_ = true; + SetNeedsCommit(); +} + } // namespace cc
diff --git a/cc/layers/layer.h b/cc/layers/layer.h index 017df68..e434412 100644 --- a/cc/layers/layer.h +++ b/cc/layers/layer.h
@@ -7,6 +7,7 @@ #include <set> #include <string> +#include <vector> #include "base/callback.h" #include "base/memory/ref_counted.h" @@ -17,6 +18,7 @@ #include "cc/base/cc_export.h" #include "cc/base/region.h" #include "cc/base/scoped_ptr_vector.h" +#include "cc/debug/frame_timing_request.h" #include "cc/debug/micro_benchmark.h" #include "cc/layers/draw_properties.h" #include "cc/layers/layer_lists.h" @@ -505,6 +507,9 @@ return has_render_surface_; } + // Sets new frame timing requests for this layer. + void SetFrameTimingRequests(const std::vector<FrameTimingRequest>& requests); + protected: friend class LayerImpl; friend class TreeSynchronizer; @@ -697,6 +702,10 @@ scoped_ptr<RenderSurface> render_surface_; gfx::Rect visible_rect_from_property_trees_; + + std::vector<FrameTimingRequest> frame_timing_requests_; + bool frame_timing_requests_dirty_; + DISALLOW_COPY_AND_ASSIGN(Layer); };
diff --git a/cc/layers/layer_impl.cc b/cc/layers/layer_impl.cc index 5bef67d..d099a63 100644 --- a/cc/layers/layer_impl.cc +++ b/cc/layers/layer_impl.cc
@@ -70,7 +70,8 @@ needs_push_properties_(false), num_dependents_need_push_properties_(0), sorting_context_id_(0), - current_draw_mode_(DRAW_MODE_NONE) { + current_draw_mode_(DRAW_MODE_NONE), + frame_timing_requests_dirty_(false) { DCHECK_GT(layer_id_, 0); DCHECK(layer_tree_impl_); layer_tree_impl_->RegisterLayer(this); @@ -607,6 +608,11 @@ layer->SetStackingOrderChanged(stacking_order_changed_); layer->SetDebugInfo(debug_info_); + if (frame_timing_requests_dirty_) { + layer->PassFrameTimingRequests(&frame_timing_requests_); + frame_timing_requests_dirty_ = false; + } + // Reset any state that should be cleared for the next update. stacking_order_changed_ = false; update_rect_ = gfx::Rect(); @@ -1024,6 +1030,13 @@ NoteLayerPropertyChangedForSubtree(); } +void LayerImpl::PassFrameTimingRequests( + std::vector<FrameTimingRequest>* requests) { + frame_timing_requests_.swap(*requests); + frame_timing_requests_dirty_ = true; + SetNeedsPushProperties(); +} + void LayerImpl::SetTransform(const gfx::Transform& transform) { if (transform_ == transform) return; @@ -1552,6 +1565,17 @@ NOTREACHED(); } } + + if (!frame_timing_requests_.empty()) { + state->BeginArray("frame_timing_requests"); + for (const auto& request : frame_timing_requests_) { + state->BeginDictionary(); + state->SetInteger("request_id", request.id()); + MathUtil::AddToTracedValue("request_rect", request.rect(), state); + state->EndDictionary(); + } + state->EndArray(); + } } bool LayerImpl::IsDrawnRenderSurfaceLayerListMember() const {
diff --git a/cc/layers/layer_impl.h b/cc/layers/layer_impl.h index d1cf053..f52b5de 100644 --- a/cc/layers/layer_impl.h +++ b/cc/layers/layer_impl.h
@@ -7,6 +7,7 @@ #include <set> #include <string> +#include <vector> #include "base/logging.h" #include "base/memory/scoped_ptr.h" @@ -18,6 +19,7 @@ #include "cc/base/cc_export.h" #include "cc/base/region.h" #include "cc/base/scoped_ptr_vector.h" +#include "cc/debug/frame_timing_request.h" #include "cc/input/input_handler.h" #include "cc/input/scrollbar.h" #include "cc/layers/draw_properties.h" @@ -566,6 +568,12 @@ void Set3dSortingContextId(int id); int sorting_context_id() { return sorting_context_id_; } + void PassFrameTimingRequests( + std::vector<FrameTimingRequest>* frame_timing_requests); + const std::vector<FrameTimingRequest>& frame_timing_requests() const { + return frame_timing_requests_; + } + protected: LayerImpl(LayerTreeImpl* layer_impl, int id); @@ -720,6 +728,10 @@ scoped_refptr<base::debug::ConvertableToTraceFormat> debug_info_; scoped_ptr<RenderSurfaceImpl> render_surface_; + + std::vector<FrameTimingRequest> frame_timing_requests_; + bool frame_timing_requests_dirty_; + DISALLOW_COPY_AND_ASSIGN(LayerImpl); };
diff --git a/cc/layers/picture_layer.cc b/cc/layers/picture_layer.cc index 98e8dcb..a55318e 100644 --- a/cc/layers/picture_layer.cc +++ b/cc/layers/picture_layer.cc
@@ -85,12 +85,11 @@ if (host->settings().use_display_lists) { recording_source_.reset(new DisplayListRecordingSource); } else { - recording_source_.reset(new PicturePile); + recording_source_.reset( + new PicturePile(host->settings().minimum_contents_scale, + host->settings().default_tile_grid_size)); } } - recording_source_->SetMinContentsScale( - host->settings().minimum_contents_scale); - recording_source_->SetTileGridSize(host->settings().default_tile_grid_size); recording_source_->SetSlowdownRasterScaleFactor( host->debug_state().slow_down_raster_scale_factor); }
diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc index 3dbce3c..813bc47 100644 --- a/cc/layers/picture_layer_impl.cc +++ b/cc/layers/picture_layer_impl.cc
@@ -82,7 +82,6 @@ low_res_raster_contents_scale_(0.f), raster_source_scale_is_fixed_(false), was_screen_space_transform_animating_(false), - should_update_tile_priorities_(false), only_used_low_res_last_append_quads_(false), is_mask_(is_mask), nearest_neighbor_(false) { @@ -462,8 +461,6 @@ if (draw_transform_is_animating()) raster_source_->SetShouldAttemptToUseDistanceFieldText(); - should_update_tile_priorities_ = true; - return UpdateTilePriorities(occlusion_in_content_space); } @@ -557,6 +554,9 @@ invalidation_.Swap(new_invalidation); bool can_have_tilings = CanHaveTilings(); + DCHECK_IMPLIES( + pending_set, + can_have_tilings == GetPendingOrActiveTwinLayer()->CanHaveTilings()); // Need to call UpdateTiles again if CanHaveTilings changed. if (could_have_tilings != can_have_tilings) @@ -589,9 +589,8 @@ void PictureLayerImpl::ReleaseResources() { // Recreate tilings with new settings, since some of those might change when - // we release resources. If tilings_ is null, then leave it as null. - if (tilings_) - tilings_ = CreatePictureLayerTilingSet(); + // we release resources. + tilings_ = CreatePictureLayerTilingSet(); ResetRasterScale(); // To avoid an edge case after lost context where the tree is up to date but @@ -784,8 +783,7 @@ } void PictureLayerImpl::RemoveAllTilings() { - if (tilings_) - tilings_->RemoveAllTilings(); + tilings_->RemoveAllTilings(); // If there are no tilings, then raster scales are no longer meaningful. ResetRasterScale(); } @@ -1076,10 +1074,6 @@ raster_contents_scale_ = 0.f; low_res_raster_contents_scale_ = 0.f; raster_source_scale_is_fixed_ = false; - - // When raster scales aren't valid, don't update tile priorities until - // this layer has been updated via UpdateDrawProperties. - should_update_tile_priorities_ = false; } bool PictureLayerImpl::CanHaveTilings() const {
diff --git a/cc/layers/picture_layer_impl.h b/cc/layers/picture_layer_impl.h index e6554cd..86f1424 100644 --- a/cc/layers/picture_layer_impl.h +++ b/cc/layers/picture_layer_impl.h
@@ -158,9 +158,6 @@ bool raster_source_scale_is_fixed_; bool was_screen_space_transform_animating_; - // A sanity state check to make sure UpdateTilePriorities only gets called - // after a CalculateContentsScale/ManageTilings. - bool should_update_tile_priorities_; bool only_used_low_res_last_append_quads_; const bool is_mask_;
diff --git a/cc/layers/picture_layer_impl_perftest.cc b/cc/layers/picture_layer_impl_perftest.cc index c1c0dbb..c649e69 100644 --- a/cc/layers/picture_layer_impl_perftest.cc +++ b/cc/layers/picture_layer_impl_perftest.cc
@@ -77,7 +77,7 @@ timer_.Reset(); do { int count = num_tiles; - scoped_ptr<TilingSetRasterQueue> queue(new TilingSetRasterQueueAll( + scoped_ptr<TilingSetRasterQueueAll> queue(new TilingSetRasterQueueAll( pending_layer_->picture_layer_tiling_set(), false)); while (count--) { ASSERT_TRUE(!queue->IsEmpty()) << "count: " << count; @@ -100,7 +100,7 @@ timer_.Reset(); do { - scoped_ptr<TilingSetRasterQueue> queue(new TilingSetRasterQueueAll( + scoped_ptr<TilingSetRasterQueueAll> queue(new TilingSetRasterQueueAll( pending_layer_->picture_layer_tiling_set(), false)); timer_.NextLap(); } while (!timer_.HasTimeLimitExpired());
diff --git a/cc/layers/picture_layer_impl_unittest.cc b/cc/layers/picture_layer_impl_unittest.cc index 0f4bf8d1..79dfec6 100644 --- a/cc/layers/picture_layer_impl_unittest.cc +++ b/cc/layers/picture_layer_impl_unittest.cc
@@ -1670,7 +1670,7 @@ int num_visible = 0; int num_offscreen = 0; - scoped_ptr<TilingSetRasterQueue> queue(new TilingSetRasterQueueAll( + scoped_ptr<TilingSetRasterQueueAll> queue(new TilingSetRasterQueueAll( pending_layer_->picture_layer_tiling_set(), false)); for (; !queue->IsEmpty(); queue->Pop()) { const Tile* tile = queue->Top(); @@ -2816,7 +2816,7 @@ int low_res_tile_count = 0u; int high_res_tile_count = 0u; int high_res_now_tiles = 0u; - scoped_ptr<TilingSetRasterQueue> queue(new TilingSetRasterQueueAll( + scoped_ptr<TilingSetRasterQueueAll> queue(new TilingSetRasterQueueAll( pending_layer_->picture_layer_tiling_set(), false)); while (!queue->IsEmpty()) { Tile* tile = queue->Top(); @@ -2855,22 +2855,23 @@ EXPECT_EQ(low_res_tile_count + high_res_tile_count + non_ideal_tile_count, static_cast<int>(unique_tiles.size())); - queue.reset(new TilingSetRasterQueueRequired( - pending_layer_->picture_layer_tiling_set(), - RasterTilePriorityQueue::Type::REQUIRED_FOR_DRAW)); - EXPECT_TRUE(queue->IsEmpty()); + scoped_ptr<TilingSetRasterQueueRequired> required_queue( + new TilingSetRasterQueueRequired( + pending_layer_->picture_layer_tiling_set(), + RasterTilePriorityQueue::Type::REQUIRED_FOR_DRAW)); + EXPECT_TRUE(required_queue->IsEmpty()); - queue.reset(new TilingSetRasterQueueRequired( + required_queue.reset(new TilingSetRasterQueueRequired( pending_layer_->picture_layer_tiling_set(), RasterTilePriorityQueue::Type::REQUIRED_FOR_ACTIVATION)); - EXPECT_FALSE(queue->IsEmpty()); + EXPECT_FALSE(required_queue->IsEmpty()); int required_for_activation_count = 0; - while (!queue->IsEmpty()) { - Tile* tile = queue->Top(); + while (!required_queue->IsEmpty()) { + Tile* tile = required_queue->Top(); EXPECT_TRUE(tile->required_for_activation()); EXPECT_FALSE(tile->IsReadyToDraw()); ++required_for_activation_count; - queue->Pop(); + required_queue->Pop(); } // All of the high res tiles should be required for activation, since there is @@ -2968,9 +2969,10 @@ ActivateTree(); EXPECT_EQ(2u, active_layer_->num_tilings()); - scoped_ptr<TilingSetRasterQueue> queue(new TilingSetRasterQueueRequired( - active_layer_->picture_layer_tiling_set(), - RasterTilePriorityQueue::Type::REQUIRED_FOR_DRAW)); + scoped_ptr<TilingSetRasterQueueRequired> queue( + new TilingSetRasterQueueRequired( + active_layer_->picture_layer_tiling_set(), + RasterTilePriorityQueue::Type::REQUIRED_FOR_DRAW)); EXPECT_FALSE(queue->IsEmpty()); while (!queue->IsEmpty()) { Tile* tile = queue->Top(); @@ -2996,9 +2998,10 @@ pending_layer_->picture_layer_tiling_set()->FindTilingWithResolution( HIGH_RESOLUTION)); - scoped_ptr<TilingSetRasterQueue> queue(new TilingSetRasterQueueRequired( - pending_layer_->picture_layer_tiling_set(), - RasterTilePriorityQueue::Type::REQUIRED_FOR_ACTIVATION)); + scoped_ptr<TilingSetRasterQueueRequired> queue( + new TilingSetRasterQueueRequired( + pending_layer_->picture_layer_tiling_set(), + RasterTilePriorityQueue::Type::REQUIRED_FOR_ACTIVATION)); EXPECT_TRUE(queue->IsEmpty()); } @@ -3973,7 +3976,7 @@ // No occlusion. int unoccluded_tile_count = 0; - scoped_ptr<TilingSetRasterQueue> queue(new TilingSetRasterQueueAll( + scoped_ptr<TilingSetRasterQueueAll> queue(new TilingSetRasterQueueAll( pending_layer_->picture_layer_tiling_set(), false)); while (!queue->IsEmpty()) { Tile* tile = queue->Top();
diff --git a/cc/layers/texture_layer.h b/cc/layers/texture_layer.h index 15c9aa0..00c9e74 100644 --- a/cc/layers/texture_layer.h +++ b/cc/layers/texture_layer.h
@@ -99,6 +99,7 @@ // Sets whether this texture should be Y-flipped at draw time. Defaults to // true. void SetFlipped(bool flipped); + bool flipped() const { return flipped_; } // Sets whether this texture should use nearest neighbor interpolation as // opposed to bilinear. Defaults to false.
diff --git a/cc/resources/display_list_recording_source.cc b/cc/resources/display_list_recording_source.cc index 64ad63b..7b98e50 100644 --- a/cc/resources/display_list_recording_source.cc +++ b/cc/resources/display_list_recording_source.cc
@@ -106,13 +106,6 @@ Clear(); } -void DisplayListRecordingSource::SetMinContentsScale(float min_contents_scale) { -} - -void DisplayListRecordingSource::SetTileGridSize( - const gfx::Size& tile_grid_size) { -} - void DisplayListRecordingSource::SetSlowdownRasterScaleFactor(int factor) { slow_down_raster_scale_factor_for_debug_ = factor; }
diff --git a/cc/resources/display_list_recording_source.h b/cc/resources/display_list_recording_source.h index bc87c12..a2c8ea6 100644 --- a/cc/resources/display_list_recording_source.h +++ b/cc/resources/display_list_recording_source.h
@@ -29,10 +29,8 @@ scoped_refptr<RasterSource> CreateRasterSource() const override; gfx::Size GetSize() const final; void SetEmptyBounds() override; - void SetMinContentsScale(float min_contents_scale) override; void SetSlowdownRasterScaleFactor(int factor) override; bool IsSuitableForGpuRasterization() const override; - void SetTileGridSize(const gfx::Size& tile_grid_size) override; void SetUnsuitableForGpuRasterizationForTesting() override; gfx::Size GetTileGridSizeForTesting() const override;
diff --git a/cc/resources/eviction_tile_priority_queue.cc b/cc/resources/eviction_tile_priority_queue.cc index 46fe5ee1..b1ca48d 100644 --- a/cc/resources/eviction_tile_priority_queue.cc +++ b/cc/resources/eviction_tile_priority_queue.cc
@@ -100,10 +100,6 @@ paired_queues_.make_heap(EvictionOrderComparator(tree_priority_)); } -void EvictionTilePriorityQueue::Reset() { - paired_queues_.clear(); -} - bool EvictionTilePriorityQueue::IsEmpty() const { return paired_queues_.empty() || paired_queues_.front()->IsEmpty(); }
diff --git a/cc/resources/eviction_tile_priority_queue.h b/cc/resources/eviction_tile_priority_queue.h index 1bf3c73..ab705f7 100644 --- a/cc/resources/eviction_tile_priority_queue.h +++ b/cc/resources/eviction_tile_priority_queue.h
@@ -42,7 +42,6 @@ void Build(const std::vector<PictureLayerImpl::Pair>& paired_layers, TreePriority tree_priority); - void Reset(); bool IsEmpty() const; Tile* Top();
diff --git a/cc/resources/picture_pile.cc b/cc/resources/picture_pile.cc index 1057d2de..f42244cf 100644 --- a/cc/resources/picture_pile.cc +++ b/cc/resources/picture_pile.cc
@@ -156,7 +156,8 @@ namespace cc { -PicturePile::PicturePile() +PicturePile::PicturePile(float min_contents_scale, + const gfx::Size& tile_grid_size) : min_contents_scale_(0), slow_down_raster_scale_factor_for_debug_(0), can_use_lcd_text_(true), @@ -166,6 +167,8 @@ pixel_record_distance_(kPixelDistanceToRecord), is_suitable_for_gpu_rasterization_(true) { tiling_.SetMaxTextureSize(gfx::Size(kBasePictureSize, kBasePictureSize)); + SetMinContentsScale(min_contents_scale); + SetTileGridSize(tile_grid_size); } PicturePile::~PicturePile() {
diff --git a/cc/resources/picture_pile.h b/cc/resources/picture_pile.h index 0a67c09..1e3368c 100644 --- a/cc/resources/picture_pile.h +++ b/cc/resources/picture_pile.h
@@ -19,7 +19,7 @@ class CC_EXPORT PicturePile : public RecordingSource { public: - PicturePile(); + PicturePile(float min_contents_scale, const gfx::Size& tile_grid_size); ~PicturePile() override; // RecordingSource overrides. @@ -34,10 +34,8 @@ scoped_refptr<RasterSource> CreateRasterSource() const override; gfx::Size GetSize() const final; void SetEmptyBounds() override; - void SetMinContentsScale(float min_contents_scale) override; void SetSlowdownRasterScaleFactor(int factor) override; bool IsSuitableForGpuRasterization() const override; - void SetTileGridSize(const gfx::Size& tile_grid_size) override; void SetUnsuitableForGpuRasterizationForTesting() override; gfx::Size GetTileGridSizeForTesting() const override; @@ -76,6 +74,9 @@ void Clear(); + void SetMinContentsScale(float min_contents_scale); + void SetTileGridSize(const gfx::Size& tile_grid_size); + gfx::Rect PaddedRect(const PictureMapKey& key) const; gfx::Rect PadRect(const gfx::Rect& rect) const;
diff --git a/cc/resources/picture_pile_unittest.cc b/cc/resources/picture_pile_unittest.cc index 98ce3b18..4e3fe15 100644 --- a/cc/resources/picture_pile_unittest.cc +++ b/cc/resources/picture_pile_unittest.cc
@@ -17,7 +17,10 @@ class PicturePileTestBase { public: - PicturePileTestBase() : min_scale_(0.125), frame_number_(0) {} + PicturePileTestBase() + : min_scale_(0.125), + pile_(min_scale_, gfx::Size(1000, 1000)), + frame_number_(0) {} void InitializeData() { pile_.SetTileGridSize(gfx::Size(1000, 1000)); @@ -53,8 +56,8 @@ } FakeContentLayerClient client_; - FakePicturePile pile_; float min_scale_; + FakePicturePile pile_; int frame_number_; };
diff --git a/cc/resources/raster_tile_priority_queue.cc b/cc/resources/raster_tile_priority_queue.cc index 08862f6..12fcaa7 100644 --- a/cc/resources/raster_tile_priority_queue.cc +++ b/cc/resources/raster_tile_priority_queue.cc
@@ -1,348 +1,36 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. +// Copyright 2015 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 "cc/resources/raster_tile_priority_queue.h" -#include "cc/resources/tiling_set_raster_queue_all.h" -#include "cc/resources/tiling_set_raster_queue_required.h" +#include "cc/resources/raster_tile_priority_queue_all.h" +#include "cc/resources/raster_tile_priority_queue_required.h" namespace cc { -namespace { - -class RasterOrderComparator { - public: - explicit RasterOrderComparator(TreePriority tree_priority) - : tree_priority_(tree_priority) {} - - bool operator()( - const RasterTilePriorityQueue::PairedTilingSetQueue* a, - const RasterTilePriorityQueue::PairedTilingSetQueue* b) const { - // Note that in this function, we have to return true if and only if - // a is strictly lower priority than b. Note that for the sake of - // completeness, empty queue is considered to have lowest priority. - if (a->IsEmpty() || b->IsEmpty()) - return b->IsEmpty() < a->IsEmpty(); - - WhichTree a_tree = a->NextTileIteratorTree(tree_priority_); - const TilingSetRasterQueue* a_queue = - a_tree == ACTIVE_TREE ? a->active_queue() : a->pending_queue(); - - WhichTree b_tree = b->NextTileIteratorTree(tree_priority_); - const TilingSetRasterQueue* b_queue = - b_tree == ACTIVE_TREE ? b->active_queue() : b->pending_queue(); - - const Tile* a_tile = a_queue->Top(); - const Tile* b_tile = b_queue->Top(); - - const TilePriority& a_priority = - a_tile->priority_for_tree_priority(tree_priority_); - const TilePriority& b_priority = - b_tile->priority_for_tree_priority(tree_priority_); - bool prioritize_low_res = tree_priority_ == SMOOTHNESS_TAKES_PRIORITY; - - // In smoothness mode, we should return pending NOW tiles before active - // EVENTUALLY tiles. So if both priorities here are eventually, we need to - // check the pending priority. - if (prioritize_low_res && - a_priority.priority_bin == TilePriority::EVENTUALLY && - b_priority.priority_bin == TilePriority::EVENTUALLY) { - bool a_is_pending_now = - a_tile->priority(PENDING_TREE).priority_bin == TilePriority::NOW; - bool b_is_pending_now = - b_tile->priority(PENDING_TREE).priority_bin == TilePriority::NOW; - if (a_is_pending_now || b_is_pending_now) - return a_is_pending_now < b_is_pending_now; - - // In case neither one is pending now, fall through. - } - - // If the bin is the same but the resolution is not, then the order will be - // determined by whether we prioritize low res or not. - // TODO(vmpstr): Remove this when TilePriority is no longer a member of Tile - // class but instead produced by the iterators. - if (b_priority.priority_bin == a_priority.priority_bin && - b_priority.resolution != a_priority.resolution) { - // Non ideal resolution should be sorted lower than other resolutions. - if (a_priority.resolution == NON_IDEAL_RESOLUTION) - return true; - - if (b_priority.resolution == NON_IDEAL_RESOLUTION) - return false; - - if (prioritize_low_res) - return b_priority.resolution == LOW_RESOLUTION; - return b_priority.resolution == HIGH_RESOLUTION; - } - - return b_priority.IsHigherPriorityThan(a_priority); - } - - private: - TreePriority tree_priority_; -}; - -WhichTree HigherPriorityTree(TreePriority tree_priority, - const TilingSetRasterQueue* active_queue, - const TilingSetRasterQueue* pending_queue, - const Tile* shared_tile) { - switch (tree_priority) { - case SMOOTHNESS_TAKES_PRIORITY: { - const Tile* active_tile = shared_tile ? shared_tile : active_queue->Top(); - const Tile* pending_tile = - shared_tile ? shared_tile : pending_queue->Top(); - - const TilePriority& active_priority = active_tile->priority(ACTIVE_TREE); - const TilePriority& pending_priority = - pending_tile->priority(PENDING_TREE); - - // If we're down to eventually bin tiles on the active tree, process the - // pending tree to allow tiles required for activation to be initialized - // when memory policy only allows prepaint. - if (active_priority.priority_bin == TilePriority::EVENTUALLY && - pending_priority.priority_bin == TilePriority::NOW) { - return PENDING_TREE; - } - return ACTIVE_TREE; - } - case NEW_CONTENT_TAKES_PRIORITY: - return PENDING_TREE; - case SAME_PRIORITY_FOR_BOTH_TREES: { - const Tile* active_tile = shared_tile ? shared_tile : active_queue->Top(); - const Tile* pending_tile = - shared_tile ? shared_tile : pending_queue->Top(); - - const TilePriority& active_priority = active_tile->priority(ACTIVE_TREE); - const TilePriority& pending_priority = - pending_tile->priority(PENDING_TREE); - - if (active_priority.IsHigherPriorityThan(pending_priority)) - return ACTIVE_TREE; - return PENDING_TREE; - } - default: - NOTREACHED(); - return ACTIVE_TREE; - } -} - -scoped_ptr<TilingSetRasterQueue> CreateTilingSetRasterQueue( - PictureLayerImpl* layer, - TreePriority tree_priority, - RasterTilePriorityQueue::Type type) { - if (!layer) - return nullptr; - PictureLayerTilingSet* tiling_set = layer->picture_layer_tiling_set(); - if (type == RasterTilePriorityQueue::Type::ALL) { - bool prioritize_low_res = tree_priority == SMOOTHNESS_TAKES_PRIORITY; - return make_scoped_ptr( - new TilingSetRasterQueueAll(tiling_set, prioritize_low_res)); - } - return make_scoped_ptr(new TilingSetRasterQueueRequired(tiling_set, type)); -} - -} // namespace - -RasterTilePriorityQueue::RasterTilePriorityQueue() { -} - -RasterTilePriorityQueue::~RasterTilePriorityQueue() { -} - -void RasterTilePriorityQueue::Build( +// static +scoped_ptr<RasterTilePriorityQueue> RasterTilePriorityQueue::Create( const std::vector<PictureLayerImpl::Pair>& paired_layers, TreePriority tree_priority, Type type) { - tree_priority_ = tree_priority; - for (std::vector<PictureLayerImpl::Pair>::const_iterator it = - paired_layers.begin(); - it != paired_layers.end(); - ++it) { - paired_queues_.push_back( - make_scoped_ptr(new PairedTilingSetQueue(*it, tree_priority_, type))); - } - paired_queues_.make_heap(RasterOrderComparator(tree_priority_)); -} - -void RasterTilePriorityQueue::Reset() { - paired_queues_.clear(); -} - -bool RasterTilePriorityQueue::IsEmpty() const { - return paired_queues_.empty() || paired_queues_.front()->IsEmpty(); -} - -Tile* RasterTilePriorityQueue::Top() { - DCHECK(!IsEmpty()); - return paired_queues_.front()->Top(tree_priority_); -} - -void RasterTilePriorityQueue::Pop() { - DCHECK(!IsEmpty()); - - paired_queues_.pop_heap(RasterOrderComparator(tree_priority_)); - PairedTilingSetQueue* paired_queue = paired_queues_.back(); - paired_queue->Pop(tree_priority_); - paired_queues_.push_heap(RasterOrderComparator(tree_priority_)); -} - -RasterTilePriorityQueue::PairedTilingSetQueue::PairedTilingSetQueue() { -} - -RasterTilePriorityQueue::PairedTilingSetQueue::PairedTilingSetQueue( - const PictureLayerImpl::Pair& layer_pair, - TreePriority tree_priority, - Type type) - : has_both_layers_(false) { switch (type) { - case RasterTilePriorityQueue::Type::ALL: - has_both_layers_ = layer_pair.active && layer_pair.pending; - active_queue_ = - CreateTilingSetRasterQueue(layer_pair.active, tree_priority, type); - pending_queue_ = - CreateTilingSetRasterQueue(layer_pair.pending, tree_priority, type); - break; - case RasterTilePriorityQueue::Type::REQUIRED_FOR_ACTIVATION: - pending_queue_ = - CreateTilingSetRasterQueue(layer_pair.pending, tree_priority, type); - break; - case RasterTilePriorityQueue::Type::REQUIRED_FOR_DRAW: - active_queue_ = - CreateTilingSetRasterQueue(layer_pair.active, tree_priority, type); - break; + case Type::ALL: { + scoped_ptr<RasterTilePriorityQueueAll> queue( + new RasterTilePriorityQueueAll); + queue->Build(paired_layers, tree_priority); + return queue.Pass(); + } + case Type::REQUIRED_FOR_ACTIVATION: + case Type::REQUIRED_FOR_DRAW: { + scoped_ptr<RasterTilePriorityQueueRequired> queue( + new RasterTilePriorityQueueRequired); + queue->Build(paired_layers, type); + return queue.Pass(); + } } - DCHECK_IMPLIES(has_both_layers_, active_queue_ && pending_queue_); - - SkipTilesReturnedByTwin(tree_priority); - - TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"), - "PairedTilingSetQueue::PairedTilingSetQueue", - TRACE_EVENT_SCOPE_THREAD, "state", StateAsValue()); -} - -RasterTilePriorityQueue::PairedTilingSetQueue::~PairedTilingSetQueue() { - TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"), - "PairedTilingSetQueue::~PairedTilingSetQueue", - TRACE_EVENT_SCOPE_THREAD, "state", StateAsValue()); -} - -bool RasterTilePriorityQueue::PairedTilingSetQueue::IsEmpty() const { - return (!active_queue_ || active_queue_->IsEmpty()) && - (!pending_queue_ || pending_queue_->IsEmpty()); -} - -Tile* RasterTilePriorityQueue::PairedTilingSetQueue::Top( - TreePriority tree_priority) { - DCHECK(!IsEmpty()); - - WhichTree next_tree = NextTileIteratorTree(tree_priority); - TilingSetRasterQueue* next_queue = - next_tree == ACTIVE_TREE ? active_queue_.get() : pending_queue_.get(); - DCHECK(next_queue && !next_queue->IsEmpty()); - Tile* tile = next_queue->Top(); - DCHECK(returned_tiles_for_debug_.find(tile) == - returned_tiles_for_debug_.end()); - return tile; -} - -void RasterTilePriorityQueue::PairedTilingSetQueue::Pop( - TreePriority tree_priority) { - DCHECK(!IsEmpty()); - - WhichTree next_tree = NextTileIteratorTree(tree_priority); - TilingSetRasterQueue* next_queue = - next_tree == ACTIVE_TREE ? active_queue_.get() : pending_queue_.get(); - DCHECK(next_queue && !next_queue->IsEmpty()); - DCHECK(returned_tiles_for_debug_.insert(next_queue->Top()).second); - next_queue->Pop(); - - SkipTilesReturnedByTwin(tree_priority); - - // If no empty, use Top to do DCHECK the next iterator. - DCHECK(IsEmpty() || Top(tree_priority)); -} - -void RasterTilePriorityQueue::PairedTilingSetQueue::SkipTilesReturnedByTwin( - TreePriority tree_priority) { - if (!has_both_layers_) - return; - - // We have both layers (active and pending) thus we can encounter shared - // tiles twice (from the active iterator and from the pending iterator). - while (!IsEmpty()) { - WhichTree next_tree = NextTileIteratorTree(tree_priority); - TilingSetRasterQueue* next_queue = - next_tree == ACTIVE_TREE ? active_queue_.get() : pending_queue_.get(); - DCHECK(next_queue && !next_queue->IsEmpty()); - - // Accept all non-shared tiles. - const Tile* tile = next_queue->Top(); - if (!tile->is_shared()) - break; - - // Accept a shared tile if the next tree is the higher priority one - // corresponding the iterator (active or pending) which usually (but due - // to spiral iterators not always) returns the shared tile first. - if (next_tree == HigherPriorityTree(tree_priority, nullptr, nullptr, tile)) - break; - - next_queue->Pop(); - } -} - -WhichTree RasterTilePriorityQueue::PairedTilingSetQueue::NextTileIteratorTree( - TreePriority tree_priority) const { - DCHECK(!IsEmpty()); - - // If we only have one queue with tiles, return it. - if (!active_queue_ || active_queue_->IsEmpty()) - return PENDING_TREE; - if (!pending_queue_ || pending_queue_->IsEmpty()) - return ACTIVE_TREE; - - // Now both iterators have tiles, so we have to decide based on tree priority. - return HigherPriorityTree(tree_priority, active_queue_.get(), - pending_queue_.get(), nullptr); -} - -scoped_refptr<base::debug::ConvertableToTraceFormat> -RasterTilePriorityQueue::PairedTilingSetQueue::StateAsValue() const { - scoped_refptr<base::debug::TracedValue> state = - new base::debug::TracedValue(); - - bool active_queue_has_tile = active_queue_ && !active_queue_->IsEmpty(); - TilePriority::PriorityBin active_priority_bin = TilePriority::EVENTUALLY; - TilePriority::PriorityBin pending_priority_bin = TilePriority::EVENTUALLY; - if (active_queue_has_tile) { - active_priority_bin = - active_queue_->Top()->priority(ACTIVE_TREE).priority_bin; - pending_priority_bin = - active_queue_->Top()->priority(PENDING_TREE).priority_bin; - } - - state->BeginDictionary("active_queue"); - state->SetBoolean("has_tile", active_queue_has_tile); - state->SetInteger("active_priority_bin", active_priority_bin); - state->SetInteger("pending_priority_bin", pending_priority_bin); - state->EndDictionary(); - - bool pending_queue_has_tile = pending_queue_ && !pending_queue_->IsEmpty(); - active_priority_bin = TilePriority::EVENTUALLY; - pending_priority_bin = TilePriority::EVENTUALLY; - if (pending_queue_has_tile) { - active_priority_bin = - pending_queue_->Top()->priority(ACTIVE_TREE).priority_bin; - pending_priority_bin = - pending_queue_->Top()->priority(PENDING_TREE).priority_bin; - } - - state->BeginDictionary("pending_queue"); - state->SetBoolean("has_tile", active_queue_has_tile); - state->SetInteger("active_priority_bin", active_priority_bin); - state->SetInteger("pending_priority_bin", pending_priority_bin); - state->EndDictionary(); - return state; + NOTREACHED(); + return nullptr; } } // namespace cc
diff --git a/cc/resources/raster_tile_priority_queue.h b/cc/resources/raster_tile_priority_queue.h index 65c92479..5ee99f1 100644 --- a/cc/resources/raster_tile_priority_queue.h +++ b/cc/resources/raster_tile_priority_queue.h
@@ -5,77 +5,35 @@ #ifndef CC_RESOURCES_RASTER_TILE_PRIORITY_QUEUE_H_ #define CC_RESOURCES_RASTER_TILE_PRIORITY_QUEUE_H_ -#include <set> -#include <utility> #include <vector> #include "cc/base/cc_export.h" #include "cc/layers/picture_layer_impl.h" #include "cc/resources/tile_priority.h" -#include "cc/resources/tiling_set_raster_queue.h" namespace cc { +class Tile; -// TODO(vmpstr): Consider virtualizing this and adding ::Create with the -// parameters of ::Build that would create a simpler queue for required only -// tiles (ie, there's no need for the heap if all we're interested in are the -// required tiles. class CC_EXPORT RasterTilePriorityQueue { public: enum class Type { ALL, REQUIRED_FOR_ACTIVATION, REQUIRED_FOR_DRAW }; - class PairedTilingSetQueue { - public: - PairedTilingSetQueue(); - PairedTilingSetQueue(const PictureLayerImpl::Pair& layer_pair, - TreePriority tree_priority, - Type type); - ~PairedTilingSetQueue(); + // TODO(vmpstr): Make this work with PictureLayerTilingSet pairs instead. + static scoped_ptr<RasterTilePriorityQueue> Create( + const std::vector<PictureLayerImpl::Pair>& paired_layers, + TreePriority tree_priority, + Type type); - bool IsEmpty() const; - Tile* Top(TreePriority tree_priority); - void Pop(TreePriority tree_priority); + virtual ~RasterTilePriorityQueue() {} - WhichTree NextTileIteratorTree(TreePriority tree_priority) const; - void SkipTilesReturnedByTwin(TreePriority tree_priority); + virtual bool IsEmpty() const = 0; + virtual Tile* Top() = 0; + virtual void Pop() = 0; - scoped_refptr<base::debug::ConvertableToTraceFormat> StateAsValue() const; - - const TilingSetRasterQueue* active_queue() const { - return active_queue_.get(); - } - const TilingSetRasterQueue* pending_queue() const { - return pending_queue_.get(); - } - - private: - scoped_ptr<TilingSetRasterQueue> active_queue_; - scoped_ptr<TilingSetRasterQueue> pending_queue_; - bool has_both_layers_; - - // Set of returned tiles (excluding the current one) for DCHECKing. - std::set<const Tile*> returned_tiles_for_debug_; - }; - - RasterTilePriorityQueue(); - ~RasterTilePriorityQueue(); - - void Build(const std::vector<PictureLayerImpl::Pair>& paired_layers, - TreePriority tree_priority, - Type type); - void Reset(); - - bool IsEmpty() const; - Tile* Top(); - void Pop(); + protected: + RasterTilePriorityQueue() {} private: - // TODO(vmpstr): This is potentially unnecessary if it becomes the case that - // PairedTilingSetQueue is fast enough to copy. In that case, we can use - // objects directly (ie std::vector<PairedTilingSetQueue>. - ScopedPtrVector<PairedTilingSetQueue> paired_queues_; - TreePriority tree_priority_; - DISALLOW_COPY_AND_ASSIGN(RasterTilePriorityQueue); };
diff --git a/cc/resources/raster_tile_priority_queue_all.cc b/cc/resources/raster_tile_priority_queue_all.cc new file mode 100644 index 0000000..e9836cd --- /dev/null +++ b/cc/resources/raster_tile_priority_queue_all.cc
@@ -0,0 +1,322 @@ +// Copyright 2015 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 "cc/resources/raster_tile_priority_queue_all.h" + +#include "cc/resources/tiling_set_raster_queue_all.h" + +namespace cc { + +namespace { + +class RasterOrderComparator { + public: + explicit RasterOrderComparator(TreePriority tree_priority) + : tree_priority_(tree_priority) {} + + bool operator()( + const RasterTilePriorityQueueAll::PairedTilingSetQueue* a, + const RasterTilePriorityQueueAll::PairedTilingSetQueue* b) const { + // Note that in this function, we have to return true if and only if + // a is strictly lower priority than b. Note that for the sake of + // completeness, empty queue is considered to have lowest priority. + if (a->IsEmpty() || b->IsEmpty()) + return b->IsEmpty() < a->IsEmpty(); + + WhichTree a_tree = a->NextTileIteratorTree(tree_priority_); + const TilingSetRasterQueueAll* a_queue = + a_tree == ACTIVE_TREE ? a->active_queue() : a->pending_queue(); + + WhichTree b_tree = b->NextTileIteratorTree(tree_priority_); + const TilingSetRasterQueueAll* b_queue = + b_tree == ACTIVE_TREE ? b->active_queue() : b->pending_queue(); + + const Tile* a_tile = a_queue->Top(); + const Tile* b_tile = b_queue->Top(); + + const TilePriority& a_priority = + a_tile->priority_for_tree_priority(tree_priority_); + const TilePriority& b_priority = + b_tile->priority_for_tree_priority(tree_priority_); + bool prioritize_low_res = tree_priority_ == SMOOTHNESS_TAKES_PRIORITY; + + // In smoothness mode, we should return pending NOW tiles before active + // EVENTUALLY tiles. So if both priorities here are eventually, we need to + // check the pending priority. + if (prioritize_low_res && + a_priority.priority_bin == TilePriority::EVENTUALLY && + b_priority.priority_bin == TilePriority::EVENTUALLY) { + bool a_is_pending_now = + a_tile->priority(PENDING_TREE).priority_bin == TilePriority::NOW; + bool b_is_pending_now = + b_tile->priority(PENDING_TREE).priority_bin == TilePriority::NOW; + if (a_is_pending_now || b_is_pending_now) + return a_is_pending_now < b_is_pending_now; + + // In case neither one is pending now, fall through. + } + + // If the bin is the same but the resolution is not, then the order will be + // determined by whether we prioritize low res or not. + // TODO(vmpstr): Remove this when TilePriority is no longer a member of Tile + // class but instead produced by the iterators. + if (b_priority.priority_bin == a_priority.priority_bin && + b_priority.resolution != a_priority.resolution) { + // Non ideal resolution should be sorted lower than other resolutions. + if (a_priority.resolution == NON_IDEAL_RESOLUTION) + return true; + + if (b_priority.resolution == NON_IDEAL_RESOLUTION) + return false; + + if (prioritize_low_res) + return b_priority.resolution == LOW_RESOLUTION; + return b_priority.resolution == HIGH_RESOLUTION; + } + + return b_priority.IsHigherPriorityThan(a_priority); + } + + private: + TreePriority tree_priority_; +}; + +WhichTree HigherPriorityTree(TreePriority tree_priority, + const TilingSetRasterQueueAll* active_queue, + const TilingSetRasterQueueAll* pending_queue, + const Tile* shared_tile) { + switch (tree_priority) { + case SMOOTHNESS_TAKES_PRIORITY: { + const Tile* active_tile = shared_tile ? shared_tile : active_queue->Top(); + const Tile* pending_tile = + shared_tile ? shared_tile : pending_queue->Top(); + + const TilePriority& active_priority = active_tile->priority(ACTIVE_TREE); + const TilePriority& pending_priority = + pending_tile->priority(PENDING_TREE); + + // If we're down to eventually bin tiles on the active tree, process the + // pending tree to allow tiles required for activation to be initialized + // when memory policy only allows prepaint. + if (active_priority.priority_bin == TilePriority::EVENTUALLY && + pending_priority.priority_bin == TilePriority::NOW) { + return PENDING_TREE; + } + return ACTIVE_TREE; + } + case NEW_CONTENT_TAKES_PRIORITY: + return PENDING_TREE; + case SAME_PRIORITY_FOR_BOTH_TREES: { + const Tile* active_tile = shared_tile ? shared_tile : active_queue->Top(); + const Tile* pending_tile = + shared_tile ? shared_tile : pending_queue->Top(); + + const TilePriority& active_priority = active_tile->priority(ACTIVE_TREE); + const TilePriority& pending_priority = + pending_tile->priority(PENDING_TREE); + + if (active_priority.IsHigherPriorityThan(pending_priority)) + return ACTIVE_TREE; + return PENDING_TREE; + } + default: + NOTREACHED(); + return ACTIVE_TREE; + } +} + +scoped_ptr<TilingSetRasterQueueAll> CreateTilingSetRasterQueue( + PictureLayerImpl* layer, + TreePriority tree_priority) { + if (!layer) + return nullptr; + PictureLayerTilingSet* tiling_set = layer->picture_layer_tiling_set(); + bool prioritize_low_res = tree_priority == SMOOTHNESS_TAKES_PRIORITY; + return make_scoped_ptr( + new TilingSetRasterQueueAll(tiling_set, prioritize_low_res)); +} + +} // namespace + +RasterTilePriorityQueueAll::RasterTilePriorityQueueAll() { +} + +RasterTilePriorityQueueAll::~RasterTilePriorityQueueAll() { +} + +void RasterTilePriorityQueueAll::Build( + const std::vector<PictureLayerImpl::Pair>& paired_layers, + TreePriority tree_priority) { + tree_priority_ = tree_priority; + for (std::vector<PictureLayerImpl::Pair>::const_iterator it = + paired_layers.begin(); + it != paired_layers.end(); ++it) { + paired_queues_.push_back( + make_scoped_ptr(new PairedTilingSetQueue(*it, tree_priority_))); + } + paired_queues_.make_heap(RasterOrderComparator(tree_priority_)); +} + +bool RasterTilePriorityQueueAll::IsEmpty() const { + return paired_queues_.empty() || paired_queues_.front()->IsEmpty(); +} + +Tile* RasterTilePriorityQueueAll::Top() { + DCHECK(!IsEmpty()); + return paired_queues_.front()->Top(tree_priority_); +} + +void RasterTilePriorityQueueAll::Pop() { + DCHECK(!IsEmpty()); + + paired_queues_.pop_heap(RasterOrderComparator(tree_priority_)); + PairedTilingSetQueue* paired_queue = paired_queues_.back(); + paired_queue->Pop(tree_priority_); + paired_queues_.push_heap(RasterOrderComparator(tree_priority_)); +} + +RasterTilePriorityQueueAll::PairedTilingSetQueue::PairedTilingSetQueue() { +} + +RasterTilePriorityQueueAll::PairedTilingSetQueue::PairedTilingSetQueue( + const PictureLayerImpl::Pair& layer_pair, + TreePriority tree_priority) + : active_queue_( + CreateTilingSetRasterQueue(layer_pair.active, tree_priority)), + pending_queue_( + CreateTilingSetRasterQueue(layer_pair.pending, tree_priority)), + has_both_layers_(layer_pair.active && layer_pair.pending) { + SkipTilesReturnedByTwin(tree_priority); + + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"), + "PairedTilingSetQueue::PairedTilingSetQueue", + TRACE_EVENT_SCOPE_THREAD, "state", StateAsValue()); +} + +RasterTilePriorityQueueAll::PairedTilingSetQueue::~PairedTilingSetQueue() { + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"), + "PairedTilingSetQueue::~PairedTilingSetQueue", + TRACE_EVENT_SCOPE_THREAD, "state", StateAsValue()); +} + +bool RasterTilePriorityQueueAll::PairedTilingSetQueue::IsEmpty() const { + return (!active_queue_ || active_queue_->IsEmpty()) && + (!pending_queue_ || pending_queue_->IsEmpty()); +} + +Tile* RasterTilePriorityQueueAll::PairedTilingSetQueue::Top( + TreePriority tree_priority) { + DCHECK(!IsEmpty()); + + WhichTree next_tree = NextTileIteratorTree(tree_priority); + TilingSetRasterQueueAll* next_queue = + next_tree == ACTIVE_TREE ? active_queue_.get() : pending_queue_.get(); + DCHECK(next_queue && !next_queue->IsEmpty()); + Tile* tile = next_queue->Top(); + DCHECK(returned_tiles_for_debug_.find(tile) == + returned_tiles_for_debug_.end()); + return tile; +} + +void RasterTilePriorityQueueAll::PairedTilingSetQueue::Pop( + TreePriority tree_priority) { + DCHECK(!IsEmpty()); + + WhichTree next_tree = NextTileIteratorTree(tree_priority); + TilingSetRasterQueueAll* next_queue = + next_tree == ACTIVE_TREE ? active_queue_.get() : pending_queue_.get(); + DCHECK(next_queue && !next_queue->IsEmpty()); + DCHECK(returned_tiles_for_debug_.insert(next_queue->Top()).second); + next_queue->Pop(); + + SkipTilesReturnedByTwin(tree_priority); + + // If no empty, use Top to do DCHECK the next iterator. + DCHECK(IsEmpty() || Top(tree_priority)); +} + +void RasterTilePriorityQueueAll::PairedTilingSetQueue::SkipTilesReturnedByTwin( + TreePriority tree_priority) { + if (!has_both_layers_) + return; + + // We have both layers (active and pending) thus we can encounter shared + // tiles twice (from the active iterator and from the pending iterator). + while (!IsEmpty()) { + WhichTree next_tree = NextTileIteratorTree(tree_priority); + TilingSetRasterQueueAll* next_queue = + next_tree == ACTIVE_TREE ? active_queue_.get() : pending_queue_.get(); + DCHECK(next_queue && !next_queue->IsEmpty()); + + // Accept all non-shared tiles. + const Tile* tile = next_queue->Top(); + if (!tile->is_shared()) + break; + + // Accept a shared tile if the next tree is the higher priority one + // corresponding the iterator (active or pending) which usually (but due + // to spiral iterators not always) returns the shared tile first. + if (next_tree == HigherPriorityTree(tree_priority, nullptr, nullptr, tile)) + break; + + next_queue->Pop(); + } +} + +WhichTree +RasterTilePriorityQueueAll::PairedTilingSetQueue::NextTileIteratorTree( + TreePriority tree_priority) const { + DCHECK(!IsEmpty()); + + // If we only have one queue with tiles, return it. + if (!active_queue_ || active_queue_->IsEmpty()) + return PENDING_TREE; + if (!pending_queue_ || pending_queue_->IsEmpty()) + return ACTIVE_TREE; + + // Now both iterators have tiles, so we have to decide based on tree priority. + return HigherPriorityTree(tree_priority, active_queue_.get(), + pending_queue_.get(), nullptr); +} + +scoped_refptr<base::debug::ConvertableToTraceFormat> +RasterTilePriorityQueueAll::PairedTilingSetQueue::StateAsValue() const { + scoped_refptr<base::debug::TracedValue> state = + new base::debug::TracedValue(); + + bool active_queue_has_tile = active_queue_ && !active_queue_->IsEmpty(); + TilePriority::PriorityBin active_priority_bin = TilePriority::EVENTUALLY; + TilePriority::PriorityBin pending_priority_bin = TilePriority::EVENTUALLY; + if (active_queue_has_tile) { + active_priority_bin = + active_queue_->Top()->priority(ACTIVE_TREE).priority_bin; + pending_priority_bin = + active_queue_->Top()->priority(PENDING_TREE).priority_bin; + } + + state->BeginDictionary("active_queue"); + state->SetBoolean("has_tile", active_queue_has_tile); + state->SetInteger("active_priority_bin", active_priority_bin); + state->SetInteger("pending_priority_bin", pending_priority_bin); + state->EndDictionary(); + + bool pending_queue_has_tile = pending_queue_ && !pending_queue_->IsEmpty(); + active_priority_bin = TilePriority::EVENTUALLY; + pending_priority_bin = TilePriority::EVENTUALLY; + if (pending_queue_has_tile) { + active_priority_bin = + pending_queue_->Top()->priority(ACTIVE_TREE).priority_bin; + pending_priority_bin = + pending_queue_->Top()->priority(PENDING_TREE).priority_bin; + } + + state->BeginDictionary("pending_queue"); + state->SetBoolean("has_tile", active_queue_has_tile); + state->SetInteger("active_priority_bin", active_priority_bin); + state->SetInteger("pending_priority_bin", pending_priority_bin); + state->EndDictionary(); + return state; +} + +} // namespace cc
diff --git a/cc/resources/raster_tile_priority_queue_all.h b/cc/resources/raster_tile_priority_queue_all.h new file mode 100644 index 0000000..c2b8910 --- /dev/null +++ b/cc/resources/raster_tile_priority_queue_all.h
@@ -0,0 +1,78 @@ +// Copyright 2015 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 CC_RESOURCES_RASTER_TILE_PRIORITY_QUEUE_ALL_H_ +#define CC_RESOURCES_RASTER_TILE_PRIORITY_QUEUE_ALL_H_ + +#include <set> +#include <utility> +#include <vector> + +#include "cc/base/cc_export.h" +#include "cc/layers/picture_layer_impl.h" +#include "cc/resources/raster_tile_priority_queue.h" +#include "cc/resources/tile_priority.h" +#include "cc/resources/tiling_set_raster_queue_all.h" + +namespace cc { + +class CC_EXPORT RasterTilePriorityQueueAll : public RasterTilePriorityQueue { + public: + class PairedTilingSetQueue { + public: + PairedTilingSetQueue(); + PairedTilingSetQueue(const PictureLayerImpl::Pair& layer_pair, + TreePriority tree_priority); + ~PairedTilingSetQueue(); + + bool IsEmpty() const; + Tile* Top(TreePriority tree_priority); + void Pop(TreePriority tree_priority); + + WhichTree NextTileIteratorTree(TreePriority tree_priority) const; + void SkipTilesReturnedByTwin(TreePriority tree_priority); + + scoped_refptr<base::debug::ConvertableToTraceFormat> StateAsValue() const; + + const TilingSetRasterQueueAll* active_queue() const { + return active_queue_.get(); + } + const TilingSetRasterQueueAll* pending_queue() const { + return pending_queue_.get(); + } + + private: + scoped_ptr<TilingSetRasterQueueAll> active_queue_; + scoped_ptr<TilingSetRasterQueueAll> pending_queue_; + bool has_both_layers_; + + // Set of returned tiles (excluding the current one) for DCHECKing. + std::set<const Tile*> returned_tiles_for_debug_; + }; + + RasterTilePriorityQueueAll(); + ~RasterTilePriorityQueueAll() override; + + bool IsEmpty() const override; + Tile* Top() override; + void Pop() override; + + private: + friend class RasterTilePriorityQueue; + + void Build(const std::vector<PictureLayerImpl::Pair>& paired_layers, + TreePriority tree_priority); + + // TODO(vmpstr): This is potentially unnecessary if it becomes the case that + // PairedTilingSetQueue is fast enough to copy. In that case, we can use + // objects directly (ie std::vector<PairedTilingSetQueue>. + ScopedPtrVector<PairedTilingSetQueue> paired_queues_; + TreePriority tree_priority_; + + DISALLOW_COPY_AND_ASSIGN(RasterTilePriorityQueueAll); +}; + +} // namespace cc + +#endif // CC_RESOURCES_RASTER_TILE_PRIORITY_QUEUE_ALL_H_
diff --git a/cc/resources/raster_tile_priority_queue_required.cc b/cc/resources/raster_tile_priority_queue_required.cc new file mode 100644 index 0000000..3bf00ed --- /dev/null +++ b/cc/resources/raster_tile_priority_queue_required.cc
@@ -0,0 +1,55 @@ +// Copyright 2015 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 "cc/resources/raster_tile_priority_queue_required.h" + +#include "cc/resources/tiling_set_raster_queue_required.h" + +namespace cc { + +RasterTilePriorityQueueRequired::RasterTilePriorityQueueRequired() { +} + +RasterTilePriorityQueueRequired::~RasterTilePriorityQueueRequired() { +} + +void RasterTilePriorityQueueRequired::Build( + const std::vector<PictureLayerImpl::Pair>& paired_layers, + Type type) { + DCHECK_NE(static_cast<int>(type), static_cast<int>(Type::ALL)); + for (const auto& pair : paired_layers) { + PictureLayerTilingSet* tiling_set = nullptr; + if (type == Type::REQUIRED_FOR_DRAW && pair.active) + tiling_set = pair.active->picture_layer_tiling_set(); + else if (type == Type::REQUIRED_FOR_ACTIVATION && pair.pending) + tiling_set = pair.pending->picture_layer_tiling_set(); + + if (!tiling_set) + continue; + + scoped_ptr<TilingSetRasterQueueRequired> tiling_set_queue( + new TilingSetRasterQueueRequired(tiling_set, type)); + if (tiling_set_queue->IsEmpty()) + continue; + tiling_set_queues_.push_back(tiling_set_queue.Pass()); + } +} + +bool RasterTilePriorityQueueRequired::IsEmpty() const { + return tiling_set_queues_.empty(); +} + +Tile* RasterTilePriorityQueueRequired::Top() { + DCHECK(!IsEmpty()); + return tiling_set_queues_.back()->Top(); +} + +void RasterTilePriorityQueueRequired::Pop() { + DCHECK(!IsEmpty()); + tiling_set_queues_.back()->Pop(); + if (tiling_set_queues_.back()->IsEmpty()) + tiling_set_queues_.pop_back(); +} + +} // namespace cc
diff --git a/cc/resources/raster_tile_priority_queue_required.h b/cc/resources/raster_tile_priority_queue_required.h new file mode 100644 index 0000000..02af2a6 --- /dev/null +++ b/cc/resources/raster_tile_priority_queue_required.h
@@ -0,0 +1,39 @@ +// Copyright 2015 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 CC_RESOURCES_RASTER_TILE_PRIORITY_QUEUE_REQUIRED_H_ +#define CC_RESOURCES_RASTER_TILE_PRIORITY_QUEUE_REQUIRED_H_ + +#include <vector> + +#include "cc/layers/picture_layer_impl.h" +#include "cc/resources/raster_tile_priority_queue.h" +#include "cc/resources/tiling_set_raster_queue_required.h" + +namespace cc { +class Tile; + +class RasterTilePriorityQueueRequired : public RasterTilePriorityQueue { + public: + RasterTilePriorityQueueRequired(); + ~RasterTilePriorityQueueRequired() override; + + bool IsEmpty() const override; + Tile* Top() override; + void Pop() override; + + private: + friend class RasterTilePriorityQueue; + + void Build(const std::vector<PictureLayerImpl::Pair>& paired_layers, + Type type); + + ScopedPtrVector<TilingSetRasterQueueRequired> tiling_set_queues_; + + DISALLOW_COPY_AND_ASSIGN(RasterTilePriorityQueueRequired); +}; + +} // namespace cc + +#endif // CC_RESOURCES_RASTER_TILE_PRIORITY_QUEUE_REQUIRED_H_
diff --git a/cc/resources/recording_source.h b/cc/resources/recording_source.h index 7af2255..1e45047 100644 --- a/cc/resources/recording_source.h +++ b/cc/resources/recording_source.h
@@ -37,13 +37,9 @@ virtual gfx::Size GetSize() const = 0; virtual void SetEmptyBounds() = 0; - virtual void SetMinContentsScale(float min_contents_scale) = 0; virtual void SetSlowdownRasterScaleFactor(int factor) = 0; virtual bool IsSuitableForGpuRasterization() const = 0; - // TODO(hendrikw): This is an implementation detail, remove it when possible. - virtual void SetTileGridSize(const gfx::Size& tile_grid_size) = 0; - // TODO(hendrikw): Figure out how to remove this. virtual void SetUnsuitableForGpuRasterizationForTesting() = 0; virtual gfx::Size GetTileGridSizeForTesting() const = 0;
diff --git a/cc/resources/tile_manager.cc b/cc/resources/tile_manager.cc index 81ae8b5..f5c61f3 100644 --- a/cc/resources/tile_manager.cc +++ b/cc/resources/tile_manager.cc
@@ -240,7 +240,6 @@ task_runner_.get(), base::Bind(&TileManager::CheckIfMoreTilesNeedToBePrepared, base::Unretained(this))), - eviction_priority_queue_is_up_to_date_(false), did_notify_ready_to_activate_(false), did_notify_ready_to_draw_(false) { tile_task_runner_->SetClient(this); @@ -360,11 +359,11 @@ CleanUpReleasedTiles(); TileVector tiles_that_need_to_be_rasterized; - RasterTilePriorityQueue raster_priority_queue; - client_->BuildRasterQueue(&raster_priority_queue, - global_state_.tree_priority, - RasterTilePriorityQueue::Type::ALL); - AssignGpuMemoryToTiles(&raster_priority_queue, scheduled_raster_task_limit_, + scoped_ptr<RasterTilePriorityQueue> raster_priority_queue( + client_->BuildRasterQueue(global_state_.tree_priority, + RasterTilePriorityQueue::Type::ALL)); + AssignGpuMemoryToTiles(raster_priority_queue.get(), + scheduled_raster_task_limit_, &tiles_that_need_to_be_rasterized); // Schedule tile tasks. @@ -374,15 +373,12 @@ did_notify_ready_to_draw_ = false; } else { if (global_state_.hard_memory_limit_in_bytes == 0) { - // TODO(vmpstr): Add a function to unconditionally create an eviction - // queue and guard the rest of the calls sites with this flag, instead of - // clearing here and building, which is a bit awkward. - eviction_priority_queue_is_up_to_date_ = false; resource_pool_->CheckBusyResources(false); MemoryUsage memory_limit(0, 0); MemoryUsage memory_usage(resource_pool_->acquired_memory_usage_bytes(), resource_pool_->acquired_resource_count()); - FreeTileResourcesUntilUsageIsWithinLimit(memory_limit, &memory_usage); + FreeTileResourcesUntilUsageIsWithinLimit(nullptr, memory_limit, + &memory_usage); } did_notify_ready_to_activate_ = false; @@ -411,12 +407,12 @@ FreeResourcesForReleasedTiles(); CleanUpReleasedTiles(); - RasterTilePriorityQueue required_for_draw_queue; - client_->BuildRasterQueue(&required_for_draw_queue, - global_state_.tree_priority, - RasterTilePriorityQueue::Type::REQUIRED_FOR_DRAW); + scoped_ptr<RasterTilePriorityQueue> required_for_draw_queue( + client_->BuildRasterQueue( + global_state_.tree_priority, + RasterTilePriorityQueue::Type::REQUIRED_FOR_DRAW)); TileVector tiles_that_need_to_be_rasterized; - AssignGpuMemoryToTiles(&required_for_draw_queue, + AssignGpuMemoryToTiles(required_for_draw_queue.get(), std::numeric_limits<size_t>::max(), &tiles_that_need_to_be_rasterized); @@ -433,15 +429,14 @@ // assigned memory after reaching a steady memory state. // TODO(hendrikw): Figure out why this would improve jank on some tests - See // crbug.com/449288 - required_for_draw_queue.Reset(); - client_->BuildRasterQueue(&required_for_draw_queue, - global_state_.tree_priority, - RasterTilePriorityQueue::Type::REQUIRED_FOR_DRAW); + required_for_draw_queue = client_->BuildRasterQueue( + global_state_.tree_priority, + RasterTilePriorityQueue::Type::REQUIRED_FOR_DRAW); // Use on-demand raster for any tiles that have not been been assigned // memory. This ensures that we draw even when OOM. - for (; !required_for_draw_queue.IsEmpty(); required_for_draw_queue.Pop()) { - Tile* tile = required_for_draw_queue.Top(); + for (; !required_for_draw_queue->IsEmpty(); required_for_draw_queue->Pop()) { + Tile* tile = required_for_draw_queue->Top(); tile->draw_info().set_rasterize_on_demand(); client_->NotifyTileStateChanged(tile); } @@ -492,54 +487,50 @@ state->EndDictionary(); } -void TileManager::RebuildEvictionQueueIfNeeded() { - TRACE_EVENT1("cc", - "TileManager::RebuildEvictionQueueIfNeeded", - "eviction_priority_queue_is_up_to_date", - eviction_priority_queue_is_up_to_date_); - if (eviction_priority_queue_is_up_to_date_) - return; - - eviction_priority_queue_.Reset(); - client_->BuildEvictionQueue(&eviction_priority_queue_, - global_state_.tree_priority); - eviction_priority_queue_is_up_to_date_ = true; -} - -bool TileManager::FreeTileResourcesUntilUsageIsWithinLimit( +scoped_ptr<EvictionTilePriorityQueue> +TileManager::FreeTileResourcesUntilUsageIsWithinLimit( + scoped_ptr<EvictionTilePriorityQueue> eviction_priority_queue, const MemoryUsage& limit, MemoryUsage* usage) { while (usage->Exceeds(limit)) { - RebuildEvictionQueueIfNeeded(); - if (eviction_priority_queue_.IsEmpty()) - return false; + if (!eviction_priority_queue) { + eviction_priority_queue = + client_->BuildEvictionQueue(global_state_.tree_priority); + } + if (eviction_priority_queue->IsEmpty()) + break; - Tile* tile = eviction_priority_queue_.Top(); + Tile* tile = eviction_priority_queue->Top(); *usage -= MemoryUsage::FromTile(tile); FreeResourcesForTileAndNotifyClientIfTileWasReadyToDraw(tile); - eviction_priority_queue_.Pop(); + eviction_priority_queue->Pop(); } - return true; + return eviction_priority_queue; } -bool TileManager::FreeTileResourcesWithLowerPriorityUntilUsageIsWithinLimit( +scoped_ptr<EvictionTilePriorityQueue> +TileManager::FreeTileResourcesWithLowerPriorityUntilUsageIsWithinLimit( + scoped_ptr<EvictionTilePriorityQueue> eviction_priority_queue, const MemoryUsage& limit, const TilePriority& other_priority, MemoryUsage* usage) { while (usage->Exceeds(limit)) { - RebuildEvictionQueueIfNeeded(); - if (eviction_priority_queue_.IsEmpty()) - return false; + if (!eviction_priority_queue) { + eviction_priority_queue = + client_->BuildEvictionQueue(global_state_.tree_priority); + } + if (eviction_priority_queue->IsEmpty()) + break; - Tile* tile = eviction_priority_queue_.Top(); + Tile* tile = eviction_priority_queue->Top(); if (!other_priority.IsHigherPriorityThan(tile->combined_priority())) - return false; + break; *usage -= MemoryUsage::FromTile(tile); FreeResourcesForTileAndNotifyClientIfTileWasReadyToDraw(tile); - eviction_priority_queue_.Pop(); + eviction_priority_queue->Pop(); } - return true; + return eviction_priority_queue; } bool TileManager::TilePriorityViolatesMemoryPolicy( @@ -584,7 +575,7 @@ MemoryUsage memory_usage(resource_pool_->acquired_memory_usage_bytes(), resource_pool_->acquired_resource_count()); - eviction_priority_queue_is_up_to_date_ = false; + scoped_ptr<EvictionTilePriorityQueue> eviction_priority_queue; for (; !raster_priority_queue->IsEmpty(); raster_priority_queue->Pop()) { Tile* tile = raster_priority_queue->Top(); TilePriority priority = tile->combined_priority(); @@ -626,10 +617,14 @@ MemoryUsage& tile_memory_limit = tile_is_needed_now ? hard_memory_limit : soft_memory_limit; - bool memory_usage_is_within_limit = + const MemoryUsage& scheduled_tile_memory_limit = + tile_memory_limit - memory_required_by_tile_to_be_scheduled; + eviction_priority_queue = FreeTileResourcesWithLowerPriorityUntilUsageIsWithinLimit( - tile_memory_limit - memory_required_by_tile_to_be_scheduled, + eviction_priority_queue.Pass(), scheduled_tile_memory_limit, priority, &memory_usage); + bool memory_usage_is_within_limit = + !memory_usage.Exceeds(scheduled_tile_memory_limit); // If we couldn't fit the tile into our current memory limit, then we're // done. @@ -647,7 +642,8 @@ // Note that we should try and further reduce memory in case the above loop // didn't reduce memory. This ensures that we always release as many resources // as possible to stay within the memory limit. - FreeTileResourcesUntilUsageIsWithinLimit(hard_memory_limit, &memory_usage); + eviction_priority_queue = FreeTileResourcesUntilUsageIsWithinLimit( + eviction_priority_queue.Pass(), hard_memory_limit, &memory_usage); UMA_HISTOGRAM_BOOLEAN("TileManager.ExceededMemoryBudget", !had_enough_memory_to_schedule_tiles_needed_now); @@ -944,10 +940,11 @@ // When OOM, keep re-assigning memory until we reach a steady state // where top-priority tiles are initialized. TileVector tiles_that_need_to_be_rasterized; - RasterTilePriorityQueue raster_priority_queue; - client_->BuildRasterQueue(&raster_priority_queue, global_state_.tree_priority, - RasterTilePriorityQueue::Type::ALL); - AssignGpuMemoryToTiles(&raster_priority_queue, scheduled_raster_task_limit_, + scoped_ptr<RasterTilePriorityQueue> raster_priority_queue( + client_->BuildRasterQueue(global_state_.tree_priority, + RasterTilePriorityQueue::Type::ALL)); + AssignGpuMemoryToTiles(raster_priority_queue.get(), + scheduled_raster_task_limit_, &tiles_that_need_to_be_rasterized); // |tiles_that_need_to_be_rasterized| will be empty when we reach a @@ -977,20 +974,20 @@ // we used for AssignGpuMemoryToTiles, since the AssignGpuMemoryToTiles call // could have evicted some tiles that would not be picked up by the old raster // queue. - RasterTilePriorityQueue required_for_activation_queue; - client_->BuildRasterQueue( - &required_for_activation_queue, global_state_.tree_priority, - RasterTilePriorityQueue::Type::REQUIRED_FOR_ACTIVATION); + scoped_ptr<RasterTilePriorityQueue> required_for_activation_queue( + client_->BuildRasterQueue( + global_state_.tree_priority, + RasterTilePriorityQueue::Type::REQUIRED_FOR_ACTIVATION)); // If we have tiles to mark as rasterize on demand, but we don't allow // rasterize on demand, then skip activation and return early. - if (!required_for_activation_queue.IsEmpty() && !allow_rasterize_on_demand) + if (!required_for_activation_queue->IsEmpty() && !allow_rasterize_on_demand) return; // Mark required tiles as rasterize on demand. - for (; !required_for_activation_queue.IsEmpty(); - required_for_activation_queue.Pop()) { - Tile* tile = required_for_activation_queue.Top(); + for (; !required_for_activation_queue->IsEmpty(); + required_for_activation_queue->Pop()) { + Tile* tile = required_for_activation_queue->Top(); tile->draw_info().set_rasterize_on_demand(); client_->NotifyTileStateChanged(tile); }
diff --git a/cc/resources/tile_manager.h b/cc/resources/tile_manager.h index e93373a..0e672e5 100644 --- a/cc/resources/tile_manager.h +++ b/cc/resources/tile_manager.h
@@ -60,15 +60,15 @@ // Given an empty raster tile priority queue, this will build a priority queue // that will return tiles in order in which they should be rasterized. // Note if the queue was previous built, Reset must be called on it. - virtual void BuildRasterQueue(RasterTilePriorityQueue* queue, - TreePriority tree_priority, - RasterTilePriorityQueue::Type type) = 0; + virtual scoped_ptr<RasterTilePriorityQueue> BuildRasterQueue( + TreePriority tree_priority, + RasterTilePriorityQueue::Type type) = 0; // Given an empty eviction tile priority queue, this will build a priority // queue that will return tiles in order in which they should be evicted. // Note if the queue was previous built, Reset must be called on it. - virtual void BuildEvictionQueue(EvictionTilePriorityQueue* queue, - TreePriority tree_priority) = 0; + virtual scoped_ptr<EvictionTilePriorityQueue> BuildEvictionQueue( + TreePriority tree_priority) = 0; protected: virtual ~TileManagerClient() {} @@ -247,10 +247,14 @@ SkPixelRef* pixel_ref); scoped_refptr<RasterTask> CreateRasterTask(Tile* tile); - void RebuildEvictionQueueIfNeeded(); - bool FreeTileResourcesUntilUsageIsWithinLimit(const MemoryUsage& limit, - MemoryUsage* usage); - bool FreeTileResourcesWithLowerPriorityUntilUsageIsWithinLimit( + scoped_ptr<EvictionTilePriorityQueue> + FreeTileResourcesUntilUsageIsWithinLimit( + scoped_ptr<EvictionTilePriorityQueue> eviction_priority_queue, + const MemoryUsage& limit, + MemoryUsage* usage); + scoped_ptr<EvictionTilePriorityQueue> + FreeTileResourcesWithLowerPriorityUntilUsageIsWithinLimit( + scoped_ptr<EvictionTilePriorityQueue> eviction_priority_queue, const MemoryUsage& limit, const TilePriority& oother_priority, MemoryUsage* usage); @@ -305,9 +309,6 @@ UniqueNotifier ready_to_draw_check_notifier_; UniqueNotifier more_tiles_need_prepare_check_notifier_; - EvictionTilePriorityQueue eviction_priority_queue_; - bool eviction_priority_queue_is_up_to_date_; - bool did_notify_ready_to_activate_; bool did_notify_ready_to_draw_;
diff --git a/cc/resources/tile_manager_perftest.cc b/cc/resources/tile_manager_perftest.cc index 911e5c9b..acb00e0 100644 --- a/cc/resources/tile_manager_perftest.cc +++ b/cc/resources/tile_manager_perftest.cc
@@ -180,9 +180,8 @@ timer_.Reset(); do { - RasterTilePriorityQueue queue; - host_impl_.BuildRasterQueue(&queue, priorities[priority_count], - RasterTilePriorityQueue::Type::ALL); + scoped_ptr<RasterTilePriorityQueue> queue(host_impl_.BuildRasterQueue( + priorities[priority_count], RasterTilePriorityQueue::Type::ALL)); priority_count = (priority_count + 1) % arraysize(priorities); timer_.NextLap(); } while (!timer_.HasTimeLimitExpired()); @@ -211,13 +210,12 @@ timer_.Reset(); do { int count = tile_count; - RasterTilePriorityQueue queue; - host_impl_.BuildRasterQueue(&queue, priorities[priority_count], - RasterTilePriorityQueue::Type::ALL); + scoped_ptr<RasterTilePriorityQueue> queue(host_impl_.BuildRasterQueue( + priorities[priority_count], RasterTilePriorityQueue::Type::ALL)); while (count--) { - ASSERT_FALSE(queue.IsEmpty()); - ASSERT_TRUE(queue.Top() != NULL); - queue.Pop(); + ASSERT_FALSE(queue->IsEmpty()); + ASSERT_TRUE(queue->Top() != NULL); + queue->Pop(); } priority_count = (priority_count + 1) % arraysize(priorities); timer_.NextLap(); @@ -251,8 +249,8 @@ timer_.Reset(); do { - EvictionTilePriorityQueue queue; - host_impl_.BuildEvictionQueue(&queue, priorities[priority_count]); + scoped_ptr<EvictionTilePriorityQueue> queue( + host_impl_.BuildEvictionQueue(priorities[priority_count])); priority_count = (priority_count + 1) % arraysize(priorities); timer_.NextLap(); } while (!timer_.HasTimeLimitExpired()); @@ -287,12 +285,12 @@ timer_.Reset(); do { int count = tile_count; - EvictionTilePriorityQueue queue; - host_impl_.BuildEvictionQueue(&queue, priorities[priority_count]); + scoped_ptr<EvictionTilePriorityQueue> queue( + host_impl_.BuildEvictionQueue(priorities[priority_count])); while (count--) { - ASSERT_FALSE(queue.IsEmpty()); - ASSERT_TRUE(queue.Top() != NULL); - queue.Pop(); + ASSERT_FALSE(queue->IsEmpty()); + ASSERT_TRUE(queue->Top() != NULL); + queue->Pop(); } priority_count = (priority_count + 1) % arraysize(priorities); timer_.NextLap();
diff --git a/cc/resources/tile_manager_unittest.cc b/cc/resources/tile_manager_unittest.cc index aae4e3f..8b5ab3f4 100644 --- a/cc/resources/tile_manager_unittest.cc +++ b/cc/resources/tile_manager_unittest.cc
@@ -151,18 +151,17 @@ host_impl_.SetViewportSize(layer_bounds); SetupDefaultTrees(layer_bounds); - RasterTilePriorityQueue queue; - host_impl_.BuildRasterQueue(&queue, SAME_PRIORITY_FOR_BOTH_TREES, - RasterTilePriorityQueue::Type::ALL); - EXPECT_FALSE(queue.IsEmpty()); + scoped_ptr<RasterTilePriorityQueue> queue(host_impl_.BuildRasterQueue( + SAME_PRIORITY_FOR_BOTH_TREES, RasterTilePriorityQueue::Type::ALL)); + EXPECT_FALSE(queue->IsEmpty()); size_t tile_count = 0; std::set<Tile*> all_tiles; - while (!queue.IsEmpty()) { - EXPECT_TRUE(queue.Top()); - all_tiles.insert(queue.Top()); + while (!queue->IsEmpty()) { + EXPECT_TRUE(queue->Top()); + all_tiles.insert(queue->Top()); ++tile_count; - queue.Pop(); + queue->Pop(); } EXPECT_EQ(tile_count, all_tiles.size()); @@ -170,12 +169,11 @@ // Sanity check, all tiles should be visible. std::set<Tile*> smoothness_tiles; - queue.Reset(); - host_impl_.BuildRasterQueue(&queue, SMOOTHNESS_TAKES_PRIORITY, - RasterTilePriorityQueue::Type::ALL); + queue = host_impl_.BuildRasterQueue(SMOOTHNESS_TAKES_PRIORITY, + RasterTilePriorityQueue::Type::ALL); bool had_low_res = false; - while (!queue.IsEmpty()) { - Tile* tile = queue.Top(); + while (!queue->IsEmpty()) { + Tile* tile = queue->Top(); EXPECT_TRUE(tile); EXPECT_EQ(TilePriority::NOW, tile->priority(ACTIVE_TREE).priority_bin); EXPECT_EQ(TilePriority::NOW, tile->priority(PENDING_TREE).priority_bin); @@ -183,35 +181,34 @@ had_low_res = true; else smoothness_tiles.insert(tile); - queue.Pop(); + queue->Pop(); } EXPECT_EQ(all_tiles, smoothness_tiles); EXPECT_TRUE(had_low_res); // Check that everything is required for activation. - queue.Reset(); - host_impl_.BuildRasterQueue( - &queue, SMOOTHNESS_TAKES_PRIORITY, + queue = host_impl_.BuildRasterQueue( + SMOOTHNESS_TAKES_PRIORITY, RasterTilePriorityQueue::Type::REQUIRED_FOR_ACTIVATION); std::set<Tile*> required_for_activation_tiles; - while (!queue.IsEmpty()) { - Tile* tile = queue.Top(); + while (!queue->IsEmpty()) { + Tile* tile = queue->Top(); EXPECT_TRUE(tile->required_for_activation()); required_for_activation_tiles.insert(tile); - queue.Pop(); + queue->Pop(); } EXPECT_EQ(all_tiles, required_for_activation_tiles); // Check that everything is required for draw. - queue.Reset(); - host_impl_.BuildRasterQueue(&queue, SMOOTHNESS_TAKES_PRIORITY, - RasterTilePriorityQueue::Type::REQUIRED_FOR_DRAW); + queue = host_impl_.BuildRasterQueue( + SMOOTHNESS_TAKES_PRIORITY, + RasterTilePriorityQueue::Type::REQUIRED_FOR_DRAW); std::set<Tile*> required_for_draw_tiles; - while (!queue.IsEmpty()) { - Tile* tile = queue.Top(); + while (!queue->IsEmpty()) { + Tile* tile = queue->Top(); EXPECT_TRUE(tile->required_for_draw()); required_for_draw_tiles.insert(tile); - queue.Pop(); + queue->Pop(); } EXPECT_EQ(all_tiles, required_for_draw_tiles); @@ -268,13 +265,12 @@ tile_count = 0; size_t correct_order_tiles = 0u; // Here we expect to get increasing ACTIVE_TREE priority_bin. - queue.Reset(); - host_impl_.BuildRasterQueue(&queue, SMOOTHNESS_TAKES_PRIORITY, - RasterTilePriorityQueue::Type::ALL); + queue = host_impl_.BuildRasterQueue(SMOOTHNESS_TAKES_PRIORITY, + RasterTilePriorityQueue::Type::ALL); std::set<Tile*> expected_required_for_draw_tiles; std::set<Tile*> expected_required_for_activation_tiles; - while (!queue.IsEmpty()) { - Tile* tile = queue.Top(); + while (!queue->IsEmpty()) { + Tile* tile = queue->Top(); EXPECT_TRUE(tile); if (!last_tile) @@ -312,7 +308,7 @@ expected_required_for_draw_tiles.insert(tile); if (tile->required_for_activation()) expected_required_for_activation_tiles.insert(tile); - queue.Pop(); + queue->Pop(); } EXPECT_EQ(tile_count, smoothness_tiles.size()); @@ -322,31 +318,30 @@ EXPECT_GT(correct_order_tiles, 3 * tile_count / 4); // Check that we have consistent required_for_activation tiles. - queue.Reset(); - host_impl_.BuildRasterQueue( - &queue, SMOOTHNESS_TAKES_PRIORITY, + queue = host_impl_.BuildRasterQueue( + SMOOTHNESS_TAKES_PRIORITY, RasterTilePriorityQueue::Type::REQUIRED_FOR_ACTIVATION); required_for_activation_tiles.clear(); - while (!queue.IsEmpty()) { - Tile* tile = queue.Top(); + while (!queue->IsEmpty()) { + Tile* tile = queue->Top(); EXPECT_TRUE(tile->required_for_activation()); required_for_activation_tiles.insert(tile); - queue.Pop(); + queue->Pop(); } EXPECT_EQ(expected_required_for_activation_tiles, required_for_activation_tiles); EXPECT_NE(all_tiles, required_for_activation_tiles); // Check that we have consistent required_for_draw tiles. - queue.Reset(); - host_impl_.BuildRasterQueue(&queue, SMOOTHNESS_TAKES_PRIORITY, - RasterTilePriorityQueue::Type::REQUIRED_FOR_DRAW); + queue = host_impl_.BuildRasterQueue( + SMOOTHNESS_TAKES_PRIORITY, + RasterTilePriorityQueue::Type::REQUIRED_FOR_DRAW); required_for_draw_tiles.clear(); - while (!queue.IsEmpty()) { - Tile* tile = queue.Top(); + while (!queue->IsEmpty()) { + Tile* tile = queue->Top(); EXPECT_TRUE(tile->required_for_draw()); required_for_draw_tiles.insert(tile); - queue.Pop(); + queue->Pop(); } EXPECT_EQ(expected_required_for_draw_tiles, required_for_draw_tiles); EXPECT_NE(all_tiles, required_for_draw_tiles); @@ -355,12 +350,11 @@ last_tile = NULL; size_t increasing_distance_tiles = 0u; // Here we expect to get increasing PENDING_TREE priority_bin. - queue.Reset(); - host_impl_.BuildRasterQueue(&queue, NEW_CONTENT_TAKES_PRIORITY, - RasterTilePriorityQueue::Type::ALL); + queue = host_impl_.BuildRasterQueue(NEW_CONTENT_TAKES_PRIORITY, + RasterTilePriorityQueue::Type::ALL); tile_count = 0; - while (!queue.IsEmpty()) { - Tile* tile = queue.Top(); + while (!queue->IsEmpty()) { + Tile* tile = queue->Top(); EXPECT_TRUE(tile); if (!last_tile) @@ -385,7 +379,7 @@ last_tile = tile; new_content_tiles.insert(tile); ++tile_count; - queue.Pop(); + queue->Pop(); } EXPECT_EQ(tile_count, new_content_tiles.size()); @@ -395,31 +389,30 @@ EXPECT_GE(increasing_distance_tiles, 3 * tile_count / 4); // Check that we have consistent required_for_activation tiles. - queue.Reset(); - host_impl_.BuildRasterQueue( - &queue, NEW_CONTENT_TAKES_PRIORITY, + queue = host_impl_.BuildRasterQueue( + NEW_CONTENT_TAKES_PRIORITY, RasterTilePriorityQueue::Type::REQUIRED_FOR_ACTIVATION); required_for_activation_tiles.clear(); - while (!queue.IsEmpty()) { - Tile* tile = queue.Top(); + while (!queue->IsEmpty()) { + Tile* tile = queue->Top(); EXPECT_TRUE(tile->required_for_activation()); required_for_activation_tiles.insert(tile); - queue.Pop(); + queue->Pop(); } EXPECT_EQ(expected_required_for_activation_tiles, required_for_activation_tiles); EXPECT_NE(new_content_tiles, required_for_activation_tiles); // Check that we have consistent required_for_draw tiles. - queue.Reset(); - host_impl_.BuildRasterQueue(&queue, NEW_CONTENT_TAKES_PRIORITY, - RasterTilePriorityQueue::Type::REQUIRED_FOR_DRAW); + queue = host_impl_.BuildRasterQueue( + NEW_CONTENT_TAKES_PRIORITY, + RasterTilePriorityQueue::Type::REQUIRED_FOR_DRAW); required_for_draw_tiles.clear(); - while (!queue.IsEmpty()) { - Tile* tile = queue.Top(); + while (!queue->IsEmpty()) { + Tile* tile = queue->Top(); EXPECT_TRUE(tile->required_for_draw()); required_for_draw_tiles.insert(tile); - queue.Pop(); + queue->Pop(); } EXPECT_EQ(expected_required_for_draw_tiles, required_for_draw_tiles); EXPECT_NE(new_content_tiles, required_for_draw_tiles); @@ -485,14 +478,13 @@ // The actual test will now build different queues and verify that the queues // return the same information as computed manually above. - RasterTilePriorityQueue queue; - host_impl_.BuildRasterQueue(&queue, SAME_PRIORITY_FOR_BOTH_TREES, - RasterTilePriorityQueue::Type::ALL); + scoped_ptr<RasterTilePriorityQueue> queue(host_impl_.BuildRasterQueue( + SAME_PRIORITY_FOR_BOTH_TREES, RasterTilePriorityQueue::Type::ALL)); std::set<Tile*> actual_now_tiles; std::set<Tile*> actual_all_tiles; - while (!queue.IsEmpty()) { - Tile* tile = queue.Top(); - queue.Pop(); + while (!queue->IsEmpty()) { + Tile* tile = queue->Top(); + queue->Pop(); if (tile->combined_priority().priority_bin == TilePriority::NOW) actual_now_tiles.insert(tile); actual_all_tiles.insert(tile); @@ -500,25 +492,24 @@ EXPECT_EQ(expected_now_tiles, actual_now_tiles); EXPECT_EQ(expected_all_tiles, actual_all_tiles); - queue.Reset(); - host_impl_.BuildRasterQueue(&queue, SAME_PRIORITY_FOR_BOTH_TREES, - RasterTilePriorityQueue::Type::REQUIRED_FOR_DRAW); + queue = host_impl_.BuildRasterQueue( + SAME_PRIORITY_FOR_BOTH_TREES, + RasterTilePriorityQueue::Type::REQUIRED_FOR_DRAW); std::set<Tile*> actual_required_for_draw_tiles; - while (!queue.IsEmpty()) { - Tile* tile = queue.Top(); - queue.Pop(); + while (!queue->IsEmpty()) { + Tile* tile = queue->Top(); + queue->Pop(); actual_required_for_draw_tiles.insert(tile); } EXPECT_EQ(expected_required_for_draw_tiles, actual_required_for_draw_tiles); - queue.Reset(); - host_impl_.BuildRasterQueue( - &queue, SAME_PRIORITY_FOR_BOTH_TREES, + queue = host_impl_.BuildRasterQueue( + SAME_PRIORITY_FOR_BOTH_TREES, RasterTilePriorityQueue::Type::REQUIRED_FOR_ACTIVATION); std::set<Tile*> actual_required_for_activation_tiles; - while (!queue.IsEmpty()) { - Tile* tile = queue.Top(); - queue.Pop(); + while (!queue->IsEmpty()) { + Tile* tile = queue->Top(); + queue->Pop(); actual_required_for_activation_tiles.insert(tile); } EXPECT_EQ(expected_required_for_activation_tiles, @@ -552,22 +543,21 @@ CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, time_ticks)); host_impl_.pending_tree()->UpdateDrawProperties(); - RasterTilePriorityQueue queue; host_impl_.SetRequiresHighResToDraw(); - host_impl_.BuildRasterQueue(&queue, SMOOTHNESS_TAKES_PRIORITY, - RasterTilePriorityQueue::Type::ALL); - EXPECT_FALSE(queue.IsEmpty()); + scoped_ptr<RasterTilePriorityQueue> queue(host_impl_.BuildRasterQueue( + SMOOTHNESS_TAKES_PRIORITY, RasterTilePriorityQueue::Type::ALL)); + EXPECT_FALSE(queue->IsEmpty()); // Get all the tiles that are NOW or SOON and make sure they are ready to // draw. std::vector<Tile*> all_tiles; - while (!queue.IsEmpty()) { - Tile* tile = queue.Top(); + while (!queue->IsEmpty()) { + Tile* tile = queue->Top(); if (tile->combined_priority().priority_bin >= TilePriority::EVENTUALLY) break; all_tiles.push_back(tile); - queue.Pop(); + queue->Pop(); } tile_manager()->InitializeTilesWithResourcesForTesting( @@ -583,20 +573,19 @@ host_impl_.SetViewportSize(layer_bounds); SetupDefaultTrees(layer_bounds); - EvictionTilePriorityQueue empty_queue; - host_impl_.BuildEvictionQueue(&empty_queue, SAME_PRIORITY_FOR_BOTH_TREES); - EXPECT_TRUE(empty_queue.IsEmpty()); + scoped_ptr<EvictionTilePriorityQueue> empty_queue( + host_impl_.BuildEvictionQueue(SAME_PRIORITY_FOR_BOTH_TREES)); + EXPECT_TRUE(empty_queue->IsEmpty()); std::set<Tile*> all_tiles; size_t tile_count = 0; - RasterTilePriorityQueue raster_queue; - host_impl_.BuildRasterQueue(&raster_queue, SAME_PRIORITY_FOR_BOTH_TREES, - RasterTilePriorityQueue::Type::ALL); - while (!raster_queue.IsEmpty()) { + scoped_ptr<RasterTilePriorityQueue> raster_queue(host_impl_.BuildRasterQueue( + SAME_PRIORITY_FOR_BOTH_TREES, RasterTilePriorityQueue::Type::ALL)); + while (!raster_queue->IsEmpty()) { ++tile_count; - EXPECT_TRUE(raster_queue.Top()); - all_tiles.insert(raster_queue.Top()); - raster_queue.Pop(); + EXPECT_TRUE(raster_queue->Top()); + all_tiles.insert(raster_queue->Top()); + raster_queue->Pop(); } EXPECT_EQ(tile_count, all_tiles.size()); @@ -605,20 +594,20 @@ tile_manager()->InitializeTilesWithResourcesForTesting( std::vector<Tile*>(all_tiles.begin(), all_tiles.end())); - EvictionTilePriorityQueue queue; - host_impl_.BuildEvictionQueue(&queue, SMOOTHNESS_TAKES_PRIORITY); - EXPECT_FALSE(queue.IsEmpty()); + scoped_ptr<EvictionTilePriorityQueue> queue( + host_impl_.BuildEvictionQueue(SMOOTHNESS_TAKES_PRIORITY)); + EXPECT_FALSE(queue->IsEmpty()); // Sanity check, all tiles should be visible. std::set<Tile*> smoothness_tiles; - while (!queue.IsEmpty()) { - Tile* tile = queue.Top(); + while (!queue->IsEmpty()) { + Tile* tile = queue->Top(); EXPECT_TRUE(tile); EXPECT_EQ(TilePriority::NOW, tile->priority(ACTIVE_TREE).priority_bin); EXPECT_EQ(TilePriority::NOW, tile->priority(PENDING_TREE).priority_bin); EXPECT_TRUE(tile->HasResource()); smoothness_tiles.insert(tile); - queue.Pop(); + queue->Pop(); } EXPECT_EQ(all_tiles, smoothness_tiles); @@ -675,12 +664,11 @@ smoothness_tiles.clear(); tile_count = 0; // Here we expect to get increasing ACTIVE_TREE priority_bin. - queue.Reset(); - host_impl_.BuildEvictionQueue(&queue, SMOOTHNESS_TAKES_PRIORITY); + queue = host_impl_.BuildEvictionQueue(SMOOTHNESS_TAKES_PRIORITY); int distance_increasing = 0; int distance_decreasing = 0; - while (!queue.IsEmpty()) { - Tile* tile = queue.Top(); + while (!queue->IsEmpty()) { + Tile* tile = queue->Top(); EXPECT_TRUE(tile); EXPECT_TRUE(tile->HasResource()); @@ -706,7 +694,7 @@ last_tile = tile; ++tile_count; smoothness_tiles.insert(tile); - queue.Pop(); + queue->Pop(); } EXPECT_EQ(3, distance_increasing); @@ -717,12 +705,11 @@ std::set<Tile*> new_content_tiles; last_tile = NULL; // Here we expect to get increasing PENDING_TREE priority_bin. - queue.Reset(); - host_impl_.BuildEvictionQueue(&queue, NEW_CONTENT_TAKES_PRIORITY); + queue = host_impl_.BuildEvictionQueue(NEW_CONTENT_TAKES_PRIORITY); distance_decreasing = 0; distance_increasing = 0; - while (!queue.IsEmpty()) { - Tile* tile = queue.Top(); + while (!queue->IsEmpty()) { + Tile* tile = queue->Top(); EXPECT_TRUE(tile); if (!last_tile) @@ -746,7 +733,7 @@ last_tile = tile; new_content_tiles.insert(tile); - queue.Pop(); + queue->Pop(); } EXPECT_EQ(3, distance_increasing); @@ -787,14 +774,13 @@ std::set<Tile*> all_tiles; size_t tile_count = 0; - RasterTilePriorityQueue raster_queue; - host_impl_.BuildRasterQueue(&raster_queue, SAME_PRIORITY_FOR_BOTH_TREES, - RasterTilePriorityQueue::Type::ALL); - while (!raster_queue.IsEmpty()) { + scoped_ptr<RasterTilePriorityQueue> raster_queue(host_impl_.BuildRasterQueue( + SAME_PRIORITY_FOR_BOTH_TREES, RasterTilePriorityQueue::Type::ALL)); + while (!raster_queue->IsEmpty()) { ++tile_count; - EXPECT_TRUE(raster_queue.Top()); - all_tiles.insert(raster_queue.Top()); - raster_queue.Pop(); + EXPECT_TRUE(raster_queue->Top()); + all_tiles.insert(raster_queue->Top()); + raster_queue->Pop(); } EXPECT_EQ(tile_count, all_tiles.size()); EXPECT_EQ(32u, tile_count); @@ -843,10 +829,10 @@ TreePriority tree_priority = NEW_CONTENT_TAKES_PRIORITY; size_t occluded_count = 0u; Tile* last_tile = NULL; - EvictionTilePriorityQueue queue; - host_impl_.BuildEvictionQueue(&queue, tree_priority); - while (!queue.IsEmpty()) { - Tile* tile = queue.Top(); + scoped_ptr<EvictionTilePriorityQueue> queue( + host_impl_.BuildEvictionQueue(tree_priority)); + while (!queue->IsEmpty()) { + Tile* tile = queue->Top(); if (!last_tile) last_tile = tile; @@ -872,7 +858,7 @@ } } last_tile = tile; - queue.Pop(); + queue->Pop(); } size_t expected_occluded_count = pending_child_high_res_tiles.size() + pending_child_low_res_tiles.size(); @@ -969,10 +955,10 @@ TreePriority tree_priority = NEW_CONTENT_TAKES_PRIORITY; std::set<Tile*> new_content_tiles; size_t tile_count = 0; - EvictionTilePriorityQueue queue; - host_impl_.BuildEvictionQueue(&queue, tree_priority); - while (!queue.IsEmpty()) { - Tile* tile = queue.Top(); + scoped_ptr<EvictionTilePriorityQueue> queue( + host_impl_.BuildEvictionQueue(tree_priority)); + while (!queue->IsEmpty()) { + Tile* tile = queue->Top(); const TilePriority& pending_priority = tile->priority(PENDING_TREE); EXPECT_NE(std::numeric_limits<float>::infinity(), pending_priority.distance_to_visible); @@ -982,7 +968,7 @@ EXPECT_EQ(TilePriority::NOW, pending_priority.priority_bin); new_content_tiles.insert(tile); ++tile_count; - queue.Pop(); + queue->Pop(); } EXPECT_EQ(tile_count, new_content_tiles.size()); EXPECT_EQ(all_tiles, new_content_tiles); @@ -993,24 +979,22 @@ host_impl_.SetViewportSize(layer_bounds); SetupDefaultTrees(layer_bounds); - RasterTilePriorityQueue queue; - host_impl_.BuildRasterQueue(&queue, SAME_PRIORITY_FOR_BOTH_TREES, - RasterTilePriorityQueue::Type::ALL); - EXPECT_FALSE(queue.IsEmpty()); + scoped_ptr<RasterTilePriorityQueue> queue(host_impl_.BuildRasterQueue( + SAME_PRIORITY_FOR_BOTH_TREES, RasterTilePriorityQueue::Type::ALL)); + EXPECT_FALSE(queue->IsEmpty()); size_t tile_count = 0; std::set<Tile*> all_tiles; - while (!queue.IsEmpty()) { - EXPECT_TRUE(queue.Top()); - all_tiles.insert(queue.Top()); + while (!queue->IsEmpty()) { + EXPECT_TRUE(queue->Top()); + all_tiles.insert(queue->Top()); ++tile_count; - queue.Pop(); + queue->Pop(); } EXPECT_EQ(tile_count, all_tiles.size()); EXPECT_EQ(16u, tile_count); - queue.Reset(); for (int i = 1; i < 10; ++i) { scoped_ptr<FakePictureLayerImpl> pending_layer = FakePictureLayerImpl::Create(host_impl_.pending_tree(), id_ + i); @@ -1019,17 +1003,17 @@ pending_layer_->AddChild(pending_layer.Pass()); } - host_impl_.BuildRasterQueue(&queue, SAME_PRIORITY_FOR_BOTH_TREES, - RasterTilePriorityQueue::Type::ALL); - EXPECT_FALSE(queue.IsEmpty()); + queue = host_impl_.BuildRasterQueue(SAME_PRIORITY_FOR_BOTH_TREES, + RasterTilePriorityQueue::Type::ALL); + EXPECT_FALSE(queue->IsEmpty()); tile_count = 0; all_tiles.clear(); - while (!queue.IsEmpty()) { - EXPECT_TRUE(queue.Top()); - all_tiles.insert(queue.Top()); + while (!queue->IsEmpty()) { + EXPECT_TRUE(queue->Top()); + all_tiles.insert(queue->Top()); ++tile_count; - queue.Pop(); + queue->Pop(); } EXPECT_EQ(tile_count, all_tiles.size()); EXPECT_EQ(16u, tile_count); @@ -1040,18 +1024,17 @@ host_impl_.SetViewportSize(layer_bounds); SetupDefaultTrees(layer_bounds); - RasterTilePriorityQueue raster_queue; - host_impl_.BuildRasterQueue(&raster_queue, SAME_PRIORITY_FOR_BOTH_TREES, - RasterTilePriorityQueue::Type::ALL); - EXPECT_FALSE(raster_queue.IsEmpty()); + scoped_ptr<RasterTilePriorityQueue> raster_queue(host_impl_.BuildRasterQueue( + SAME_PRIORITY_FOR_BOTH_TREES, RasterTilePriorityQueue::Type::ALL)); + EXPECT_FALSE(raster_queue->IsEmpty()); size_t tile_count = 0; std::set<Tile*> all_tiles; - while (!raster_queue.IsEmpty()) { - EXPECT_TRUE(raster_queue.Top()); - all_tiles.insert(raster_queue.Top()); + while (!raster_queue->IsEmpty()) { + EXPECT_TRUE(raster_queue->Top()); + all_tiles.insert(raster_queue->Top()); ++tile_count; - raster_queue.Pop(); + raster_queue->Pop(); } EXPECT_EQ(tile_count, all_tiles.size()); EXPECT_EQ(16u, tile_count); @@ -1059,7 +1042,6 @@ std::vector<Tile*> tiles(all_tiles.begin(), all_tiles.end()); host_impl_.tile_manager()->InitializeTilesWithResourcesForTesting(tiles); - EvictionTilePriorityQueue queue; for (int i = 1; i < 10; ++i) { scoped_ptr<FakePictureLayerImpl> pending_layer = FakePictureLayerImpl::Create(host_impl_.pending_tree(), id_ + i); @@ -1068,16 +1050,17 @@ pending_layer_->AddChild(pending_layer.Pass()); } - host_impl_.BuildEvictionQueue(&queue, SAME_PRIORITY_FOR_BOTH_TREES); - EXPECT_FALSE(queue.IsEmpty()); + scoped_ptr<EvictionTilePriorityQueue> queue( + host_impl_.BuildEvictionQueue(SAME_PRIORITY_FOR_BOTH_TREES)); + EXPECT_FALSE(queue->IsEmpty()); tile_count = 0; all_tiles.clear(); - while (!queue.IsEmpty()) { - EXPECT_TRUE(queue.Top()); - all_tiles.insert(queue.Top()); + while (!queue->IsEmpty()) { + EXPECT_TRUE(queue->Top()); + all_tiles.insert(queue->Top()); ++tile_count; - queue.Pop(); + queue->Pop(); } EXPECT_EQ(tile_count, all_tiles.size()); EXPECT_EQ(16u, tile_count); @@ -1121,7 +1104,7 @@ // 3. Third iteration ensures that no tiles are returned, since they were all // marked as ready to draw. for (int i = 0; i < 3; ++i) { - scoped_ptr<TilingSetRasterQueue> queue( + scoped_ptr<TilingSetRasterQueueAll> queue( new TilingSetRasterQueueAll(tiling_set.get(), false)); // There are 3 bins in TilePriority. @@ -1231,7 +1214,7 @@ Tile* last_tile = NULL; int eventually_bin_order_correct_count = 0; int eventually_bin_order_incorrect_count = 0; - scoped_ptr<TilingSetRasterQueue> queue( + scoped_ptr<TilingSetRasterQueueAll> queue( new TilingSetRasterQueueAll(tiling_set.get(), false)); for (; !queue->IsEmpty(); queue->Pop()) { if (!last_tile)
diff --git a/cc/resources/tiling_set_raster_queue.h b/cc/resources/tiling_set_raster_queue.h deleted file mode 100644 index 0a131a99..0000000 --- a/cc/resources/tiling_set_raster_queue.h +++ /dev/null
@@ -1,23 +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 CC_RESOURCES_TILING_SET_RASTER_QUEUE_H_ -#define CC_RESOURCES_TILING_SET_RASTER_QUEUE_H_ - -namespace cc { -class Tile; - -class TilingSetRasterQueue { - public: - virtual ~TilingSetRasterQueue() {} - - virtual Tile* Top() = 0; - virtual const Tile* Top() const = 0; - virtual void Pop() = 0; - virtual bool IsEmpty() const = 0; -}; - -} // namespace cc - -#endif // CC_RESOURCES_TILING_SET_RASTER_QUEUE_H_
diff --git a/cc/resources/tiling_set_raster_queue_all.h b/cc/resources/tiling_set_raster_queue_all.h index bea70d3..5577c6c5 100644 --- a/cc/resources/tiling_set_raster_queue_all.h +++ b/cc/resources/tiling_set_raster_queue_all.h
@@ -9,23 +9,21 @@ #include "cc/resources/picture_layer_tiling_set.h" #include "cc/resources/tile.h" #include "cc/resources/tile_priority.h" -#include "cc/resources/tiling_set_raster_queue.h" namespace cc { // This queue returns all tiles required to be rasterized from HIGH_RESOLUTION // and LOW_RESOLUTION tilings. -class CC_EXPORT TilingSetRasterQueueAll - : public NON_EXPORTED_BASE(TilingSetRasterQueue) { +class CC_EXPORT TilingSetRasterQueueAll { public: TilingSetRasterQueueAll(PictureLayerTilingSet* tiling_set, bool prioritize_low_res); - ~TilingSetRasterQueueAll() override; + ~TilingSetRasterQueueAll(); - Tile* Top() override; - const Tile* Top() const override; - void Pop() override; - bool IsEmpty() const override; + Tile* Top(); + const Tile* Top() const; + void Pop(); + bool IsEmpty() const; private: class TilingIterator {
diff --git a/cc/resources/tiling_set_raster_queue_required.h b/cc/resources/tiling_set_raster_queue_required.h index 5feb05b..6e278e6 100644 --- a/cc/resources/tiling_set_raster_queue_required.h +++ b/cc/resources/tiling_set_raster_queue_required.h
@@ -9,24 +9,22 @@ #include "cc/resources/picture_layer_tiling_set.h" #include "cc/resources/raster_tile_priority_queue.h" #include "cc/resources/tile.h" -#include "cc/resources/tiling_set_raster_queue.h" namespace cc { // This queue only returns tiles that are required for either activation or // draw, as specified by RasterTilePriorityQueue::Type passed in the // constructor. -class CC_EXPORT TilingSetRasterQueueRequired - : public NON_EXPORTED_BASE(TilingSetRasterQueue) { +class CC_EXPORT TilingSetRasterQueueRequired { public: TilingSetRasterQueueRequired(PictureLayerTilingSet* tiling_set, RasterTilePriorityQueue::Type type); - ~TilingSetRasterQueueRequired() override; + ~TilingSetRasterQueueRequired(); - Tile* Top() override; - const Tile* Top() const override; - void Pop() override; - bool IsEmpty() const override; + Tile* Top(); + const Tile* Top() const; + void Pop(); + bool IsEmpty() const; private: // This iterator will return all tiles that are in the NOW bin on the given
diff --git a/cc/scheduler/delay_based_time_source.cc b/cc/scheduler/delay_based_time_source.cc index cd214fd9..dbfdc0d 100644 --- a/cc/scheduler/delay_based_time_source.cc +++ b/cc/scheduler/delay_based_time_source.cc
@@ -36,7 +36,7 @@ } // namespace // The following methods correspond to the DelayBasedTimeSource that uses -// the base::TimeTicks::HighResNow as the timebase. +// the base::TimeTicks::Now as the timebase. scoped_refptr<DelayBasedTimeSourceHighRes> DelayBasedTimeSourceHighRes::Create( base::TimeDelta interval, base::SingleThreadTaskRunner* task_runner) { @@ -53,7 +53,7 @@ DelayBasedTimeSourceHighRes::~DelayBasedTimeSourceHighRes() {} base::TimeTicks DelayBasedTimeSourceHighRes::Now() const { - return base::TimeTicks::HighResNow(); + return base::TimeTicks::Now(); } // The following methods correspond to the DelayBasedTimeSource that uses
diff --git a/cc/scheduler/delay_based_time_source.h b/cc/scheduler/delay_based_time_source.h index 9f670d1..ea03f9d 100644 --- a/cc/scheduler/delay_based_time_source.h +++ b/cc/scheduler/delay_based_time_source.h
@@ -95,7 +95,9 @@ DISALLOW_COPY_AND_ASSIGN(DelayBasedTimeSource); }; -// DelayBasedTimeSource uses base::TimeTicks::HighResNow as its timebase. +// DelayBasedTimeSource that once used base::TimeTicks::HighResNow as its time +// source, but is now a no-op. +// TODO(brianderson): Remove along with gfx::/FrameTime.http://crbug.com/447329 class DelayBasedTimeSourceHighRes : public DelayBasedTimeSource { public: static scoped_refptr<DelayBasedTimeSourceHighRes> Create(
diff --git a/cc/scheduler/scheduler.cc b/cc/scheduler/scheduler.cc index 35f13f4..691b6dc 100644 --- a/cc/scheduler/scheduler.cc +++ b/cc/scheduler/scheduler.cc
@@ -399,7 +399,7 @@ // If the scheduler is busy, we queue the BeginFrame to be handled later as // a BeginRetroFrame. bool Scheduler::OnBeginFrameMixInDelegate(const BeginFrameArgs& args) { - TRACE_EVENT1("cc", "Scheduler::BeginFrame", "args", args.AsValue()); + TRACE_EVENT1("cc,benchmark", "Scheduler::BeginFrame", "args", args.AsValue()); // Deliver BeginFrames to children. if (settings_.forward_begin_frames_to_children && @@ -461,7 +461,7 @@ // BeginRetroFrame is called for BeginFrames that we've deferred because // the scheduler was in the middle of processing a previous BeginFrame. void Scheduler::BeginRetroFrame() { - TRACE_EVENT0("cc", "Scheduler::BeginRetroFrame"); + TRACE_EVENT0("cc,benchmark", "Scheduler::BeginRetroFrame"); DCHECK(!settings_.using_synchronous_renderer_compositor); DCHECK(!begin_retro_frame_args_.empty()); DCHECK(!begin_retro_frame_task_.IsCancelled()); @@ -537,7 +537,7 @@ void Scheduler::BeginImplFrame(const BeginFrameArgs& args) { bool main_thread_is_in_high_latency_mode = state_machine_.MainThreadIsInHighLatencyMode(); - TRACE_EVENT2("cc", + TRACE_EVENT2("cc,benchmark", "Scheduler::BeginImplFrame", "args", args.AsValue(), @@ -635,7 +635,7 @@ } void Scheduler::OnBeginImplFrameDeadline() { - TRACE_EVENT0("cc", "Scheduler::OnBeginImplFrameDeadline"); + TRACE_EVENT0("cc,benchmark", "Scheduler::OnBeginImplFrameDeadline"); begin_impl_frame_deadline_task_.Cancel(); // We split the deadline actions up into two phases so the state machine // has a chance to trigger actions that should occur durring and after
diff --git a/cc/scheduler/scheduler_state_machine.cc b/cc/scheduler/scheduler_state_machine.cc index d54907f..c3a4a1e2 100644 --- a/cc/scheduler/scheduler_state_machine.cc +++ b/cc/scheduler/scheduler_state_machine.cc
@@ -875,6 +875,12 @@ if (pending_swaps_ >= max_pending_swaps_) return false; + if (active_tree_needs_first_draw_) + return true; + + if (!needs_redraw_) + return false; + // This is used to prioritize impl-thread draws when the main thread isn't // producing anything, e.g., after an aborted commit. We also check that we // don't have a pending tree -- otherwise we should give it a chance to @@ -883,12 +889,6 @@ if (commit_state_ == COMMIT_STATE_IDLE && !has_pending_tree_) return true; - if (!needs_redraw_) - return false; - - if (active_tree_needs_first_draw_) - return true; - // Prioritize impl-thread draws in impl_latency_takes_priority_ mode. if (impl_latency_takes_priority_) return true;
diff --git a/cc/scheduler/scheduler_state_machine_unittest.cc b/cc/scheduler/scheduler_state_machine_unittest.cc index 1f377b5..95e3684 100644 --- a/cc/scheduler/scheduler_state_machine_unittest.cc +++ b/cc/scheduler/scheduler_state_machine_unittest.cc
@@ -49,6 +49,13 @@ state.OnBeginImplFrameIdle(); \ } +#define SET_UP_STATE(state) \ + state.SetCanStart(); \ + state.UpdateState(state.NextAction()); \ + state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); \ + state.SetVisible(true); \ + state.SetCanDraw(true); + namespace cc { namespace { @@ -210,12 +217,8 @@ scheduler_settings.main_frame_before_activation_enabled = true; StateMachine state(scheduler_settings); state.SetCommitState(SchedulerStateMachine::COMMIT_STATE_IDLE); - state.SetCanStart(); - state.UpdateState(state.NextAction()); - state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); + SET_UP_STATE(state) state.SetNeedsRedraw(false); - state.SetVisible(true); - state.SetCanDraw(true); state.SetNeedsCommit(); EXPECT_TRUE(state.BeginFrameNeeded()); @@ -270,11 +273,7 @@ TestFailedDrawForAnimationCheckerboardSetsNeedsCommitAndDoesNotDrawAgain) { SchedulerSettings default_scheduler_settings; StateMachine state(default_scheduler_settings); - state.SetCanStart(); - state.UpdateState(state.NextAction()); - state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); - state.SetVisible(true); - state.SetCanDraw(true); + SET_UP_STATE(state) state.SetNeedsRedraw(true); EXPECT_TRUE(state.RedrawPending()); EXPECT_TRUE(state.BeginFrameNeeded()); @@ -306,11 +305,7 @@ TEST(SchedulerStateMachineTest, TestFailedDrawForMissingHighResNeedsCommit) { SchedulerSettings default_scheduler_settings; StateMachine state(default_scheduler_settings); - state.SetCanStart(); - state.UpdateState(state.NextAction()); - state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); - state.SetVisible(true); - state.SetCanDraw(true); + SET_UP_STATE(state) state.SetNeedsRedraw(true); EXPECT_TRUE(state.RedrawPending()); EXPECT_TRUE(state.BeginFrameNeeded()); @@ -340,12 +335,7 @@ TestsetNeedsRedrawDuringFailedDrawDoesNotRemoveNeedsRedraw) { SchedulerSettings default_scheduler_settings; StateMachine state(default_scheduler_settings); - state.SetCanStart(); - state.UpdateState(state.NextAction()); - state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); - - state.SetVisible(true); - state.SetCanDraw(true); + SET_UP_STATE(state) state.SetNeedsRedraw(true); EXPECT_TRUE(state.RedrawPending()); EXPECT_TRUE(state.BeginFrameNeeded()); @@ -382,11 +372,7 @@ SchedulerSettings scheduler_settings; scheduler_settings.maximum_number_of_failed_draws_before_draw_is_forced_ = 1; StateMachine state(scheduler_settings); - state.SetCanStart(); - state.UpdateState(state.NextAction()); - state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); - state.SetVisible(true); - state.SetCanDraw(true); + SET_UP_STATE(state) // Start a commit. state.SetNeedsCommit(); @@ -440,11 +426,7 @@ draw_limit; scheduler_settings.impl_side_painting = true; StateMachine state(scheduler_settings); - state.SetCanStart(); - state.UpdateState(state.NextAction()); - state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); - state.SetVisible(true); - state.SetCanDraw(true); + SET_UP_STATE(state) // Start a commit. state.SetNeedsCommit(); @@ -497,11 +479,7 @@ TEST(SchedulerStateMachineTest, TestFailedDrawIsRetriedInNextBeginImplFrame) { SchedulerSettings default_scheduler_settings; StateMachine state(default_scheduler_settings); - state.SetCanStart(); - state.UpdateState(state.NextAction()); - state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); - state.SetVisible(true); - state.SetCanDraw(true); + SET_UP_STATE(state) // Start a draw. state.SetNeedsRedraw(true); @@ -540,11 +518,7 @@ TEST(SchedulerStateMachineTest, TestDoestDrawTwiceInSameFrame) { SchedulerSettings default_scheduler_settings; StateMachine state(default_scheduler_settings); - state.SetCanStart(); - state.UpdateState(state.NextAction()); - state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); - state.SetVisible(true); - state.SetCanDraw(true); + SET_UP_STATE(state) state.SetNeedsRedraw(true); // Draw the first frame. @@ -744,12 +718,8 @@ TEST(SchedulerStateMachineTest, TestSetNeedsCommitIsNotLost) { SchedulerSettings scheduler_settings; StateMachine state(scheduler_settings); - state.SetCanStart(); - state.UpdateState(state.NextAction()); - state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); + SET_UP_STATE(state) state.SetNeedsCommit(); - state.SetVisible(true); - state.SetCanDraw(true); EXPECT_TRUE(state.BeginFrameNeeded()); @@ -815,11 +785,7 @@ TEST(SchedulerStateMachineTest, TestFullCycle) { SchedulerSettings default_scheduler_settings; StateMachine state(default_scheduler_settings); - state.SetCanStart(); - state.UpdateState(state.NextAction()); - state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); - state.SetVisible(true); - state.SetCanDraw(true); + SET_UP_STATE(state) // Start clean and set commit. state.SetNeedsCommit(); @@ -865,11 +831,7 @@ SchedulerSettings scheduler_settings; scheduler_settings.main_thread_should_always_be_low_latency = true; StateMachine state(scheduler_settings); - state.SetCanStart(); - state.UpdateState(state.NextAction()); - state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); - state.SetVisible(true); - state.SetCanDraw(true); + SET_UP_STATE(state) // Start clean and set commit. state.SetNeedsCommit(); @@ -930,11 +892,7 @@ scheduler_settings.main_thread_should_always_be_low_latency = true; scheduler_settings.impl_side_painting = true; StateMachine state(scheduler_settings); - state.SetCanStart(); - state.UpdateState(state.NextAction()); - state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); - state.SetVisible(true); - state.SetCanDraw(true); + SET_UP_STATE(state) // Start clean and set commit. state.SetNeedsCommit(); @@ -1014,11 +972,7 @@ TEST(SchedulerStateMachineTest, TestFullCycleWithCommitRequestInbetween) { SchedulerSettings default_scheduler_settings; StateMachine state(default_scheduler_settings); - state.SetCanStart(); - state.UpdateState(state.NextAction()); - state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); - state.SetVisible(true); - state.SetCanDraw(true); + SET_UP_STATE(state) // Start clean and set commit. state.SetNeedsCommit(); @@ -1084,11 +1038,7 @@ TEST(SchedulerStateMachineTest, TestAbortBeginMainFrameBecauseInvisible) { SchedulerSettings default_scheduler_settings; StateMachine state(default_scheduler_settings); - state.SetCanStart(); - state.UpdateState(state.NextAction()); - state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); - state.SetVisible(true); - state.SetCanDraw(true); + SET_UP_STATE(state) // Start clean and set commit. state.SetNeedsCommit(); @@ -1219,12 +1169,7 @@ TEST(SchedulerStateMachineTest, TestContextLostWhenCompletelyIdle) { SchedulerSettings default_scheduler_settings; StateMachine state(default_scheduler_settings); - state.SetCanStart(); - state.UpdateState(state.NextAction()); - state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); - - state.SetVisible(true); - state.SetCanDraw(true); + SET_UP_STATE(state) EXPECT_NE(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION, state.NextAction()); @@ -1251,11 +1196,7 @@ // We use impl side painting because it's the more complicated version. default_scheduler_settings.impl_side_painting = true; StateMachine state(default_scheduler_settings); - state.SetCanStart(); - state.UpdateState(state.NextAction()); - state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); - state.SetVisible(true); - state.SetCanDraw(true); + SET_UP_STATE(state) EXPECT_NE(SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION, state.NextAction()); @@ -1378,11 +1319,7 @@ TEST(SchedulerStateMachineTest, TestContextLostWhileCommitInProgress) { SchedulerSettings scheduler_settings; StateMachine state(scheduler_settings); - state.SetCanStart(); - state.UpdateState(state.NextAction()); - state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); - state.SetVisible(true); - state.SetCanDraw(true); + SET_UP_STATE(state) // Get a commit in flight. state.SetNeedsCommit(); @@ -1442,11 +1379,7 @@ TestContextLostWhileCommitInProgressAndAnotherCommitRequested) { SchedulerSettings scheduler_settings; StateMachine state(scheduler_settings); - state.SetCanStart(); - state.UpdateState(state.NextAction()); - state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); - state.SetVisible(true); - state.SetCanDraw(true); + SET_UP_STATE(state) // Get a commit in flight. state.SetNeedsCommit(); @@ -1528,11 +1461,7 @@ TEST(SchedulerStateMachineTest, DontDrawBeforeCommitAfterLostOutputSurface) { SchedulerSettings default_scheduler_settings; StateMachine state(default_scheduler_settings); - state.SetCanStart(); - state.UpdateState(state.NextAction()); - state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); - state.SetVisible(true); - state.SetCanDraw(true); + SET_UP_STATE(state) state.SetNeedsRedraw(true); @@ -1552,11 +1481,7 @@ SchedulerSettings settings; settings.impl_side_painting = true; StateMachine state(settings); - state.SetCanStart(); - state.UpdateState(state.NextAction()); - state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); - state.SetVisible(true); - state.SetCanDraw(true); + SET_UP_STATE(state) state.SetCommitState( SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT); @@ -1609,11 +1534,7 @@ TEST(SchedulerStateMachineTest, TestInitialActionsWhenContextLost) { SchedulerSettings default_scheduler_settings; StateMachine state(default_scheduler_settings); - state.SetCanStart(); - state.UpdateState(state.NextAction()); - state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); - state.SetVisible(true); - state.SetCanDraw(true); + SET_UP_STATE(state) state.SetNeedsCommit(); state.DidLoseOutputSurface(); @@ -1636,12 +1557,7 @@ TEST(SchedulerStateMachineTest, ReportIfNotDrawing) { SchedulerSettings default_scheduler_settings; StateMachine state(default_scheduler_settings); - state.SetCanStart(); - state.UpdateState(state.NextAction()); - state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); - - state.SetCanDraw(true); - state.SetVisible(true); + SET_UP_STATE(state) EXPECT_FALSE(state.PendingDrawsShouldBeAborted()); state.SetCanDraw(false); @@ -1666,11 +1582,7 @@ SchedulerSettings settings; settings.impl_side_painting = true; StateMachine state(settings); - state.SetCanStart(); - state.UpdateState(state.NextAction()); - state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); - state.SetVisible(true); - state.SetCanDraw(true); + SET_UP_STATE(state) // This test mirrors what happens during the first frame of a scroll gesture. // First we get the input event and a BeginFrame. @@ -1724,11 +1636,7 @@ SchedulerSettings settings; settings.impl_side_painting = true; StateMachine state(settings); - state.SetCanStart(); - state.UpdateState(state.NextAction()); - state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); - state.SetVisible(true); - state.SetCanDraw(true); + SET_UP_STATE(state) // This test ensures that impl-draws are prioritized over main thread updates // in prefer impl latency mode. @@ -1782,11 +1690,7 @@ TestTriggerDeadlineImmediatelyOnLostOutputSurface) { SchedulerSettings default_scheduler_settings; StateMachine state(default_scheduler_settings); - state.SetCanStart(); - state.UpdateState(state.NextAction()); - state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); - state.SetVisible(true); - state.SetCanDraw(true); + SET_UP_STATE(state) state.SetNeedsCommit(); @@ -1806,11 +1710,7 @@ SchedulerSettings settings; settings.impl_side_painting = true; StateMachine state(settings); - state.SetCanStart(); - state.UpdateState(state.NextAction()); - state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); - state.SetVisible(true); - state.SetCanDraw(true); + SET_UP_STATE(state) // Test requesting an animation that, when run, causes us to draw. state.SetNeedsAnimate(); @@ -1830,11 +1730,7 @@ SchedulerSettings settings; settings.impl_side_painting = true; StateMachine state(settings); - state.SetCanStart(); - state.UpdateState(state.NextAction()); - state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); - state.SetVisible(true); - state.SetCanDraw(true); + SET_UP_STATE(state) // Check that animations are updated before we start a commit. state.SetNeedsAnimate(); @@ -1858,11 +1754,7 @@ SchedulerSettings settings; settings.impl_side_painting = true; StateMachine state(settings); - state.SetCanStart(); - state.UpdateState(state.NextAction()); - state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); - state.SetVisible(true); - state.SetCanDraw(true); + SET_UP_STATE(state) // Check that animations are updated before we start a commit. state.SetNeedsAnimate(); @@ -1891,11 +1783,7 @@ SchedulerSettings settings; settings.impl_side_painting = true; StateMachine state(settings); - state.SetCanStart(); - state.UpdateState(state.NextAction()); - state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); - state.SetVisible(true); - state.SetCanDraw(true); + SET_UP_STATE(state) // Test requesting an animation after we have already animated during this // frame. @@ -1918,11 +1806,7 @@ SchedulerSettings settings; settings.forward_begin_frames_to_children = true; StateMachine state(settings); - state.SetCanStart(); - state.UpdateState(state.NextAction()); - state.CreateAndInitializeOutputSurfaceWithActivatedCommit(); - state.SetVisible(true); - state.SetCanDraw(true); + SET_UP_STATE(state) EXPECT_FALSE(state.BeginFrameNeeded()); state.SetChildrenNeedBeginFrames(true);
diff --git a/cc/scheduler/scheduler_unittest.cc b/cc/scheduler/scheduler_unittest.cc index ea3cf10..29e4c49 100644 --- a/cc/scheduler/scheduler_unittest.cc +++ b/cc/scheduler/scheduler_unittest.cc
@@ -2318,34 +2318,5 @@ EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client, 0, 1); } -TEST(SchedulerTest, BeginMainFrameAbortedTriggersImmediateDeadline) { - FakeSchedulerClient client; - SchedulerSettings settings; - settings.use_external_begin_frame_source = true; - - CREATE_SCHEDULER_AND_INIT_SURFACE(settings); - - scheduler->SetNeedsCommit(); - EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client); - client.Reset(); - - client.AdvanceFrame(); - EXPECT_ACTION("WillBeginImplFrame", client, 0, 2); - EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client, 1, 2); - EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); - client.Reset(); - - client.task_runner().RunUntilTime(client.now_src()->Now()); - EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); - - scheduler->BeginMainFrameAborted(CommitEarlyOutReason::ABORTED_NOT_VISIBLE); - - EXPECT_TRUE(scheduler->BeginImplFrameDeadlinePending()); - client.task_runner().RunUntilTime(client.now_src()->Now()); - EXPECT_FALSE(scheduler->BeginImplFrameDeadlinePending()); - - EXPECT_NO_ACTION(client); -} - } // namespace } // namespace cc
diff --git a/cc/surfaces/display.cc b/cc/surfaces/display.cc index 763b81c..72c31b52 100644 --- a/cc/surfaces/display.cc +++ b/cc/surfaces/display.cc
@@ -42,6 +42,13 @@ Display::~Display() { manager_->RemoveObserver(this); + if (aggregator_) { + for (const auto& id_entry : aggregator_->previous_contained_surfaces()) { + Surface* surface = manager_->GetSurfaceForId(id_entry.first); + if (surface) + surface->RunDrawCallbacks(SurfaceDrawStatus::DRAW_SKIPPED); + } + } } bool Display::Initialize(scoped_ptr<OutputSurface> output_surface) { @@ -123,7 +130,7 @@ for (const auto& id_entry : aggregator_->previous_contained_surfaces()) { Surface* surface = manager_->GetSurfaceForId(id_entry.first); if (surface) - surface->RunDrawCallbacks(); + surface->RunDrawCallbacks(SurfaceDrawStatus::DRAWN); } DelegatedFrameData* frame_data = frame->delegated_frame_data.get(); @@ -168,7 +175,7 @@ client_->SetMemoryPolicy(policy); } -void Display::OnSurfaceDamaged(SurfaceId surface_id) { +void Display::OnSurfaceDamaged(SurfaceId surface_id, bool* changed) { if (aggregator_ && aggregator_->previous_contained_surfaces().count(surface_id)) { Surface* surface = manager_->GetSurfaceForId(surface_id); @@ -179,6 +186,10 @@ aggregator_->ReleaseResources(surface_id); } client_->DisplayDamaged(); + *changed = true; + } else if (surface_id == current_surface_id_) { + client_->DisplayDamaged(); + *changed = true; } }
diff --git a/cc/surfaces/display.h b/cc/surfaces/display.h index 47c55bb..99e66fb 100644 --- a/cc/surfaces/display.h +++ b/cc/surfaces/display.h
@@ -82,7 +82,7 @@ void SetFullRootLayerDamage() override {} // SurfaceDamageObserver implementation. - void OnSurfaceDamaged(SurfaceId surface) override; + void OnSurfaceDamaged(SurfaceId surface, bool* changed) override; private: void InitializeRenderer();
diff --git a/cc/surfaces/surface.cc b/cc/surfaces/surface.cc index 98ae58c..25f3114 100644 --- a/cc/surfaces/surface.cc +++ b/cc/surfaces/surface.cc
@@ -34,7 +34,7 @@ factory_->UnrefResources(current_resources); } if (!draw_callback_.is_null()) - draw_callback_.Run(false); + draw_callback_.Run(SurfaceDrawStatus::DRAW_SKIPPED); } void Surface::QueueFrame(scoped_ptr<CompositorFrame> frame, @@ -56,7 +56,7 @@ factory_->UnrefResources(previous_resources); } if (!draw_callback_.is_null()) - draw_callback_.Run(false); + draw_callback_.Run(SurfaceDrawStatus::DRAW_SKIPPED); draw_callback_ = callback; factory_->manager()->DidSatisfySequences( SurfaceIdAllocator::NamespaceForId(surface_id_), @@ -106,11 +106,11 @@ current_frame_->metadata.latency_info.clear(); } -void Surface::RunDrawCallbacks() { +void Surface::RunDrawCallbacks(SurfaceDrawStatus drawn) { if (!draw_callback_.is_null()) { DrawCallback callback = draw_callback_; draw_callback_ = DrawCallback(); - callback.Run(true); + callback.Run(drawn); } }
diff --git a/cc/surfaces/surface.h b/cc/surfaces/surface.h index 96152a0..8e6d7a4 100644 --- a/cc/surfaces/surface.h +++ b/cc/surfaces/surface.h
@@ -16,6 +16,7 @@ #include "cc/base/scoped_ptr_vector.h" #include "cc/output/copy_output_request.h" #include "cc/quads/render_pass_id.h" +#include "cc/surfaces/surface_factory.h" #include "cc/surfaces/surface_id.h" #include "cc/surfaces/surface_sequence.h" #include "cc/surfaces/surfaces_export.h" @@ -34,7 +35,7 @@ class CC_SURFACES_EXPORT Surface { public: - using DrawCallback = base::Callback<void(bool)>; + using DrawCallback = SurfaceFactory::DrawCallback; Surface(SurfaceId id, SurfaceFactory* factory); ~Surface(); @@ -55,7 +56,7 @@ int frame_index() const { return frame_index_; } void TakeLatencyInfo(std::vector<ui::LatencyInfo>* latency_info); - void RunDrawCallbacks(); + void RunDrawCallbacks(SurfaceDrawStatus drawn); base::WeakPtr<SurfaceFactory> factory() { return factory_; }
diff --git a/cc/surfaces/surface_aggregator.cc b/cc/surfaces/surface_aggregator.cc index 9456dd29c..15f4b53 100644 --- a/cc/surfaces/surface_aggregator.cc +++ b/cc/surfaces/surface_aggregator.cc
@@ -433,6 +433,10 @@ provider_->DestroyChild(it->second); surface_id_to_resource_child_id_.erase(it); } + + Surface* surface_ptr = manager_->GetSurfaceForId(surface.first); + if (surface_ptr) + surface_ptr->RunDrawCallbacks(SurfaceDrawStatus::DRAW_SKIPPED); } } }
diff --git a/cc/surfaces/surface_damage_observer.h b/cc/surfaces/surface_damage_observer.h index 379c9f75..62ee012 100644 --- a/cc/surfaces/surface_damage_observer.h +++ b/cc/surfaces/surface_damage_observer.h
@@ -11,7 +11,9 @@ class SurfaceDamageObserver { public: - virtual void OnSurfaceDamaged(SurfaceId surface_id) = 0; + // Runs when a Surface is damaged. *changed should be set to true if this + // causes a Display to be damaged. + virtual void OnSurfaceDamaged(SurfaceId surface_id, bool* changed) = 0; }; } // namespace cc
diff --git a/cc/surfaces/surface_factory.cc b/cc/surfaces/surface_factory.cc index 7af7cb7d..aead4f68 100644 --- a/cc/surfaces/surface_factory.cc +++ b/cc/surfaces/surface_factory.cc
@@ -51,7 +51,8 @@ DCHECK(it != surface_map_.end()); DCHECK(it->second->factory().get() == this); it->second->QueueFrame(frame.Pass(), callback); - manager_->SurfaceModified(surface_id); + if (!manager_->SurfaceModified(surface_id)) + it->second->RunDrawCallbacks(SurfaceDrawStatus::DRAW_SKIPPED); } void SurfaceFactory::RequestCopyOfSurface(
diff --git a/cc/surfaces/surface_factory.h b/cc/surfaces/surface_factory.h index 7abd929..b6b627fb 100644 --- a/cc/surfaces/surface_factory.h +++ b/cc/surfaces/surface_factory.h
@@ -27,6 +27,8 @@ class SurfaceFactoryClient; class SurfaceManager; +enum class SurfaceDrawStatus { DRAW_SKIPPED, DRAWN }; + // A SurfaceFactory is used to create surfaces that may share resources and // receive returned resources for frames submitted to those surfaces. Resources // submitted to frames created by a particular factory will be returned to that @@ -35,9 +37,7 @@ class CC_SURFACES_EXPORT SurfaceFactory : public base::SupportsWeakPtr<SurfaceFactory> { public: - // This callback is called with true if the frame was drawn, or false if it - // was discarded. - using DrawCallback = base::Callback<void(bool)>; + using DrawCallback = base::Callback<void(SurfaceDrawStatus)>; SurfaceFactory(SurfaceManager* manager, SurfaceFactoryClient* client); ~SurfaceFactory();
diff --git a/cc/surfaces/surface_factory_unittest.cc b/cc/surfaces/surface_factory_unittest.cc index 9d38689..b5c2a63 100644 --- a/cc/surfaces/surface_factory_unittest.cc +++ b/cc/surfaces/surface_factory_unittest.cc
@@ -360,8 +360,10 @@ } } -void DrawCallback(bool* executed, bool* result, bool drawn) { - *executed = true; +void DrawCallback(uint32* execute_count, + SurfaceDrawStatus* result, + SurfaceDrawStatus drawn) { + *execute_count += 1; *result = drawn; } @@ -377,17 +379,16 @@ frame_data->resource_list.push_back(resource); scoped_ptr<CompositorFrame> frame(new CompositorFrame); frame->delegated_frame_data = frame_data.Pass(); - bool executed = false; - bool drawn = false; + uint32 execute_count = 0; + SurfaceDrawStatus drawn = SurfaceDrawStatus::DRAW_SKIPPED; factory_.SubmitFrame(id, frame.Pass(), - base::Bind(&DrawCallback, &executed, &drawn)); + base::Bind(&DrawCallback, &execute_count, &drawn)); surface_id_ = SurfaceId(); - EXPECT_FALSE(executed); factory_.DestroyAll(); - EXPECT_TRUE(executed); - EXPECT_FALSE(drawn); + EXPECT_EQ(1u, execute_count); + EXPECT_EQ(SurfaceDrawStatus::DRAW_SKIPPED, drawn); } TEST_F(SurfaceFactoryTest, DestroySequence) {
diff --git a/cc/surfaces/surface_manager.cc b/cc/surfaces/surface_manager.cc index 050f04b..117d82a 100644 --- a/cc/surfaces/surface_manager.cc +++ b/cc/surfaces/surface_manager.cc
@@ -78,10 +78,12 @@ return it->second; } -void SurfaceManager::SurfaceModified(SurfaceId surface_id) { +bool SurfaceManager::SurfaceModified(SurfaceId surface_id) { DCHECK(thread_checker_.CalledOnValidThread()); - FOR_EACH_OBSERVER( - SurfaceDamageObserver, observer_list_, OnSurfaceDamaged(surface_id)); + bool changed = false; + FOR_EACH_OBSERVER(SurfaceDamageObserver, observer_list_, + OnSurfaceDamaged(surface_id, &changed)); + return changed; } } // namespace cc
diff --git a/cc/surfaces/surface_manager.h b/cc/surfaces/surface_manager.h index d6303523..d7d78c4 100644 --- a/cc/surfaces/surface_manager.h +++ b/cc/surfaces/surface_manager.h
@@ -42,7 +42,7 @@ observer_list_.RemoveObserver(obs); } - void SurfaceModified(SurfaceId surface_id); + bool SurfaceModified(SurfaceId surface_id); // A frame for a surface satisfies a set of sequence numbers in a particular // id namespace.
diff --git a/cc/test/data/scaled_render_surface_layer_gl.png b/cc/test/data/scaled_render_surface_layer_gl.png new file mode 100644 index 0000000..e5802f7a --- /dev/null +++ b/cc/test/data/scaled_render_surface_layer_gl.png Binary files differ
diff --git a/cc/test/data/scaled_render_surface_layer_sw.png b/cc/test/data/scaled_render_surface_layer_sw.png new file mode 100644 index 0000000..2a0ee21e6 --- /dev/null +++ b/cc/test/data/scaled_render_surface_layer_sw.png Binary files differ
diff --git a/cc/test/fake_picture_pile.h b/cc/test/fake_picture_pile.h index 4a7b65b..55b4c360 100644 --- a/cc/test/fake_picture_pile.h +++ b/cc/test/fake_picture_pile.h
@@ -19,7 +19,9 @@ using PictureMapKey = PicturePile::PictureMapKey; using PictureMap = PicturePile::PictureMap; - FakePicturePile() : playback_allowed_event_(nullptr) {} + FakePicturePile(float min_contents_scale, const gfx::Size& tile_grid_size) + : PicturePile(min_contents_scale, tile_grid_size), + playback_allowed_event_(nullptr) {} ~FakePicturePile() override {} // PicturePile overrides.
diff --git a/cc/test/fake_picture_pile_impl.cc b/cc/test/fake_picture_pile_impl.cc index c400298e..420b5d6 100644 --- a/cc/test/fake_picture_pile_impl.cc +++ b/cc/test/fake_picture_pile_impl.cc
@@ -32,10 +32,11 @@ scoped_refptr<FakePicturePileImpl> FakePicturePileImpl::CreateFilledPile( const gfx::Size& tile_size, const gfx::Size& layer_bounds) { - FakePicturePile pile; + FakePicturePile pile(ImplSidePaintingSettings().minimum_contents_scale, + ImplSidePaintingSettings().default_tile_grid_size); + pile.tiling().SetBorderTexels(0); pile.tiling().SetTilingSize(layer_bounds); pile.tiling().SetMaxTextureSize(tile_size); - pile.SetTileGridSize(ImplSidePaintingSettings().default_tile_grid_size); pile.SetRecordedViewport(gfx::Rect(layer_bounds)); pile.SetHasAnyRecordings(true); @@ -51,10 +52,11 @@ scoped_refptr<FakePicturePileImpl> FakePicturePileImpl::CreateEmptyPile( const gfx::Size& tile_size, const gfx::Size& layer_bounds) { - FakePicturePile pile; + FakePicturePile pile(ImplSidePaintingSettings().minimum_contents_scale, + ImplSidePaintingSettings().default_tile_grid_size); + pile.tiling().SetBorderTexels(0); pile.tiling().SetTilingSize(layer_bounds); pile.tiling().SetMaxTextureSize(tile_size); - pile.SetTileGridSize(ImplSidePaintingSettings().default_tile_grid_size); pile.SetRecordedViewport(gfx::Rect()); pile.SetHasAnyRecordings(false); return make_scoped_refptr(new FakePicturePileImpl(&pile, nullptr)); @@ -64,10 +66,11 @@ FakePicturePileImpl::CreateEmptyPileThatThinksItHasRecordings( const gfx::Size& tile_size, const gfx::Size& layer_bounds) { - FakePicturePile pile; + FakePicturePile pile(ImplSidePaintingSettings().minimum_contents_scale, + ImplSidePaintingSettings().default_tile_grid_size); + pile.tiling().SetBorderTexels(0); pile.tiling().SetTilingSize(layer_bounds); pile.tiling().SetMaxTextureSize(tile_size); - pile.SetTileGridSize(ImplSidePaintingSettings().default_tile_grid_size); // This simulates a false positive for this flag. pile.SetRecordedViewport(gfx::Rect()); pile.SetHasAnyRecordings(true); @@ -76,12 +79,12 @@ scoped_refptr<FakePicturePileImpl> FakePicturePileImpl::CreateInfiniteFilledPile() { - FakePicturePile pile; gfx::Size size(std::numeric_limits<int>::max(), std::numeric_limits<int>::max()); + FakePicturePile pile(ImplSidePaintingSettings().minimum_contents_scale, size); + pile.tiling().SetBorderTexels(0); pile.tiling().SetTilingSize(size); pile.tiling().SetMaxTextureSize(size); - pile.SetTileGridSize(size); pile.SetRecordedViewport(gfx::Rect(size)); pile.SetHasAnyRecordings(true);
diff --git a/cc/test/fake_tile_manager_client.cc b/cc/test/fake_tile_manager_client.cc index f6b3749..e22fd1e 100644 --- a/cc/test/fake_tile_manager_client.cc +++ b/cc/test/fake_tile_manager_client.cc
@@ -19,4 +19,15 @@ return picture_layers_; } +scoped_ptr<RasterTilePriorityQueue> FakeTileManagerClient::BuildRasterQueue( + TreePriority tree_priority, + RasterTilePriorityQueue::Type type) { + return nullptr; +} + +scoped_ptr<EvictionTilePriorityQueue> FakeTileManagerClient::BuildEvictionQueue( + TreePriority tree_priority) { + return nullptr; +} + } // namespace cc
diff --git a/cc/test/fake_tile_manager_client.h b/cc/test/fake_tile_manager_client.h index 843c59f..ef1eaca8 100644 --- a/cc/test/fake_tile_manager_client.h +++ b/cc/test/fake_tile_manager_client.h
@@ -21,11 +21,11 @@ void NotifyReadyToActivate() override {} void NotifyReadyToDraw() override {} void NotifyTileStateChanged(const Tile* tile) override {} - void BuildRasterQueue(RasterTilePriorityQueue* queue, - TreePriority tree_priority, - RasterTilePriorityQueue::Type type) override {} - void BuildEvictionQueue(EvictionTilePriorityQueue* queue, - TreePriority tree_priority) override {} + scoped_ptr<RasterTilePriorityQueue> BuildRasterQueue( + TreePriority tree_priority, + RasterTilePriorityQueue::Type type) override; + scoped_ptr<EvictionTilePriorityQueue> BuildEvictionQueue( + TreePriority tree_priority) override; private: std::vector<PictureLayerImpl*> picture_layers_;
diff --git a/cc/trees/layer_tree_host_common.cc b/cc/trees/layer_tree_host_common.cc index 3e70aeb3..e12e2726 100644 --- a/cc/trees/layer_tree_host_common.cc +++ b/cc/trees/layer_tree_host_common.cc
@@ -1831,14 +1831,6 @@ data_for_children.full_hierarchy_matrix = data_from_ancestor.full_hierarchy_matrix; - // If the subtree will scale layer contents by the transform hierarchy, then - // we should scale things into the render surface by the transform hierarchy - // to take advantage of that. - gfx::Vector2dF render_surface_sublayer_scale = - globals.can_adjust_raster_scales - ? combined_transform_scales - : gfx::Vector2dF(layer_scale_factors, layer_scale_factors); - bool render_to_separate_surface = IsRootLayer(layer) || (globals.can_render_to_separate_surface && layer->render_surface()); @@ -1873,17 +1865,19 @@ // space which we do not want; so here we use the combined_transform // instead of the draw_transform. However, we do need to add a different // scale factor that accounts for the surface's pixel dimensions. - combined_transform.Scale(1.0 / render_surface_sublayer_scale.x(), - 1.0 / render_surface_sublayer_scale.y()); - render_surface->SetDrawTransform(combined_transform); + // Remove the combined_transform scale from the draw transform. + gfx::Transform draw_transform = combined_transform; + draw_transform.Scale(1.0 / combined_transform_scales.x(), + 1.0 / combined_transform_scales.y()); + render_surface->SetDrawTransform(draw_transform); // The owning layer's transform was re-parented by the surface, so the // layer's new draw_transform only needs to scale the layer to surface // space. layer_draw_properties.target_space_transform.MakeIdentity(); - layer_draw_properties.target_space_transform. - Scale(render_surface_sublayer_scale.x() / layer->contents_scale_x(), - render_surface_sublayer_scale.y() / layer->contents_scale_y()); + layer_draw_properties.target_space_transform.Scale( + combined_transform_scales.x() / layer->contents_scale_x(), + combined_transform_scales.y() / layer->contents_scale_y()); // Inside the surface's subtree, we scale everything to the owning layer's // scale. The sublayer matrix transforms layer rects into target surface @@ -1892,8 +1886,8 @@ // but we apply it explicitly to the owning layer and the remainder of the // subtree independently. DCHECK(data_for_children.parent_matrix.IsIdentity()); - data_for_children.parent_matrix.Scale(render_surface_sublayer_scale.x(), - render_surface_sublayer_scale.y()); + data_for_children.parent_matrix.Scale(combined_transform_scales.x(), + combined_transform_scales.y()); // Even if the |layer_is_drawn|, it only contributes to a drawn surface // when the |layer_is_visible|. @@ -2311,14 +2305,14 @@ // surface's subtree into layer space. gfx::Transform screen_space_transform = layer->screen_space_transform(); screen_space_transform.Scale( - layer->contents_scale_x() / render_surface_sublayer_scale.x(), - layer->contents_scale_y() / render_surface_sublayer_scale.y()); + layer->contents_scale_x() / combined_transform_scales.x(), + layer->contents_scale_y() / combined_transform_scales.y()); render_surface->SetScreenSpaceTransform(screen_space_transform); if (layer->replica_layer()) { gfx::Transform surface_origin_to_replica_origin_transform; surface_origin_to_replica_origin_transform.Scale( - render_surface_sublayer_scale.x(), render_surface_sublayer_scale.y()); + combined_transform_scales.x(), combined_transform_scales.y()); surface_origin_to_replica_origin_transform.Translate( layer->replica_layer()->position().x() + layer->replica_layer()->transform_origin().x(), @@ -2330,8 +2324,8 @@ -layer->replica_layer()->transform_origin().x(), -layer->replica_layer()->transform_origin().y()); surface_origin_to_replica_origin_transform.Scale( - 1.0 / render_surface_sublayer_scale.x(), - 1.0 / render_surface_sublayer_scale.y()); + 1.0 / combined_transform_scales.x(), + 1.0 / combined_transform_scales.y()); // Compute the replica's "originTransform" that maps from the replica's // origin space to the target surface origin space.
diff --git a/cc/trees/layer_tree_host_common_unittest.cc b/cc/trees/layer_tree_host_common_unittest.cc index 01941c1..238c3cb2 100644 --- a/cc/trees/layer_tree_host_common_unittest.cc +++ b/cc/trees/layer_tree_host_common_unittest.cc
@@ -5157,75 +5157,81 @@ EXPECT_FLOAT_EQ(initial_parent_scale, parent->draw_transform().matrix().get(1, 1)); - // The child surface is scaled up during draw since its subtree is not scaled + // The child surface is not scaled up during draw since its subtree is scaled // by the transform hierarchy. EXPECT_FLOAT_EQ( - initial_parent_scale * initial_child_scale, + 1.f, surface_scale->render_surface()->draw_transform().matrix().get(0, 0)); EXPECT_FLOAT_EQ( - initial_parent_scale * initial_child_scale, + 1.f, surface_scale->render_surface()->draw_transform().matrix().get(1, 1)); - // The surface_scale's RenderSurface is scaled during draw, so the layer does - // not need to be scaled when drawing into its surface. - EXPECT_FLOAT_EQ(1.0, surface_scale->draw_transform().matrix().get(0, 0)); - EXPECT_FLOAT_EQ(1.0, surface_scale->draw_transform().matrix().get(1, 1)); + // The surface_scale's RenderSurface is not scaled during draw, so the layer + // needs to be scaled when drawing into its surface. + EXPECT_FLOAT_EQ(initial_parent_scale * initial_child_scale, + surface_scale->draw_transform().matrix().get(0, 0)); + EXPECT_FLOAT_EQ(initial_parent_scale * initial_child_scale, + surface_scale->draw_transform().matrix().get(1, 1)); - // The surface_scale_child_scale is scaled when drawing into its surface, - // since its content bounds are not scaled by the transform hierarchy. + // The surface_scale_child_scale is not scaled when drawing into its surface, + // since its content bounds are scaled by the transform hierarchy. EXPECT_FLOAT_EQ( - initial_child_scale, + initial_child_scale * initial_child_scale * initial_parent_scale, surface_scale_child_scale->draw_transform().matrix().get(0, 0)); EXPECT_FLOAT_EQ( - initial_child_scale, + initial_child_scale * initial_child_scale * initial_parent_scale, surface_scale_child_scale->draw_transform().matrix().get(1, 1)); - // The surface_scale_child_no_scale has a fixed contents scale of 1, so it - // needs to be scaled by the device and page scale factors, along with the - // transform hierarchy. + // The surface_scale_child_no_scale is scaled by the device scale, page scale + // and transform hierarchy. EXPECT_FLOAT_EQ( - device_scale_factor * page_scale_factor * initial_child_scale, + device_scale_factor * page_scale_factor * initial_parent_scale * + initial_child_scale * initial_child_scale, surface_scale_child_no_scale->draw_transform().matrix().get(0, 0)); EXPECT_FLOAT_EQ( - device_scale_factor * page_scale_factor * initial_child_scale, + device_scale_factor * page_scale_factor * initial_parent_scale * + initial_child_scale * initial_child_scale, surface_scale_child_no_scale->draw_transform().matrix().get(1, 1)); - // The child surface is scaled up during draw since its subtree is not scaled + // The child surface is not scaled up during draw since its subtree is scaled // by the transform hierarchy. EXPECT_FLOAT_EQ( - initial_parent_scale * initial_child_scale, + 1.f, surface_no_scale->render_surface()->draw_transform().matrix().get(0, 0)); EXPECT_FLOAT_EQ( - initial_parent_scale * initial_child_scale, + 1.f, surface_no_scale->render_surface()->draw_transform().matrix().get(1, 1)); // The surface_no_scale layer has a fixed contents scale of 1, so it needs to // be scaled by the device and page scale factors. Its surface is already // scaled by the transform hierarchy so those don't need to scale the layer's // drawing. - EXPECT_FLOAT_EQ(device_scale_factor * page_scale_factor, + EXPECT_FLOAT_EQ(initial_parent_scale * initial_child_scale * + device_scale_factor * page_scale_factor, surface_no_scale->draw_transform().matrix().get(0, 0)); - EXPECT_FLOAT_EQ(device_scale_factor * page_scale_factor, + EXPECT_FLOAT_EQ(initial_parent_scale * initial_child_scale * + device_scale_factor * page_scale_factor, surface_no_scale->draw_transform().matrix().get(1, 1)); // The surface_no_scale_child_scale has its contents scaled by the page and // device scale factors, but needs to be scaled by the transform hierarchy // when drawing. EXPECT_FLOAT_EQ( - initial_child_scale, + initial_parent_scale * initial_child_scale * initial_child_scale, surface_no_scale_child_scale->draw_transform().matrix().get(0, 0)); EXPECT_FLOAT_EQ( - initial_child_scale, + initial_parent_scale * initial_child_scale * initial_child_scale, surface_no_scale_child_scale->draw_transform().matrix().get(1, 1)); - // The surface_no_scale_child_no_scale has a fixed contents scale of 1, so it - // needs to be scaled by the device and page scale factors. It also needs to - // be scaled by any transform heirarchy below its target surface. + // The surface_no_scale_child_no_scale needs to be scaled by the device and + // page scale factors and by any transform heirarchy below its target surface. EXPECT_FLOAT_EQ( - device_scale_factor * page_scale_factor * initial_child_scale, + device_scale_factor * page_scale_factor * initial_parent_scale * + initial_child_scale * initial_child_scale, surface_no_scale_child_no_scale->draw_transform().matrix().get(0, 0)); EXPECT_FLOAT_EQ( - device_scale_factor * page_scale_factor * initial_child_scale, + device_scale_factor * page_scale_factor * initial_parent_scale * + initial_child_scale * initial_child_scale, surface_no_scale_child_no_scale->draw_transform().matrix().get(1, 1)); }
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index 4ec2f88..0befa0f 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc
@@ -691,7 +691,7 @@ render_surface->contributes_to_drawn_surface() || render_surface_layer->HasCopyRequest(); if (should_draw_into_render_pass) - render_surface_layer->render_surface()->AppendRenderPasses(frame); + render_surface->AppendRenderPasses(frame); } // When we are displaying the HUD, change the root damage rect to cover the @@ -1194,13 +1194,14 @@ } } -void LayerTreeHostImpl::BuildRasterQueue(RasterTilePriorityQueue* queue, - TreePriority tree_priority, - RasterTilePriorityQueue::Type type) { +scoped_ptr<RasterTilePriorityQueue> LayerTreeHostImpl::BuildRasterQueue( + TreePriority tree_priority, + RasterTilePriorityQueue::Type type) { TRACE_EVENT0("cc", "LayerTreeHostImpl::BuildRasterQueue"); picture_layer_pairs_.clear(); GetPictureLayerImplPairs(&picture_layer_pairs_, true); - queue->Build(picture_layer_pairs_, tree_priority, type); + scoped_ptr<RasterTilePriorityQueue> queue(RasterTilePriorityQueue::Create( + picture_layer_pairs_, tree_priority, type)); if (!queue->IsEmpty()) { // Only checking the Top() tile here isn't a definite answer that there is @@ -1215,14 +1216,17 @@ } else { required_for_draw_tile_is_top_of_raster_queue_ = false; } + return queue; } -void LayerTreeHostImpl::BuildEvictionQueue(EvictionTilePriorityQueue* queue, - TreePriority tree_priority) { +scoped_ptr<EvictionTilePriorityQueue> LayerTreeHostImpl::BuildEvictionQueue( + TreePriority tree_priority) { TRACE_EVENT0("cc", "LayerTreeHostImpl::BuildEvictionQueue"); + scoped_ptr<EvictionTilePriorityQueue> queue(new EvictionTilePriorityQueue); picture_layer_pairs_.clear(); GetPictureLayerImplPairs(&picture_layer_pairs_, false); queue->Build(picture_layer_pairs_, tree_priority); + return queue; } const std::vector<PictureLayerImpl*>& LayerTreeHostImpl::GetPictureLayers() @@ -1592,7 +1596,7 @@ active_tree()->FinishSwapPromises(&metadata); for (size_t i = 0; i < metadata.latency_info.size(); i++) { TRACE_EVENT_FLOW_STEP0( - "input", + "input,benchmark", "LatencyInfo.Flow", TRACE_ID_DONT_MANGLE(metadata.latency_info[i].trace_id), "SwapBuffers");
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h index 2728ff8..0765bb7a 100644 --- a/cc/trees/layer_tree_host_impl.h +++ b/cc/trees/layer_tree_host_impl.h
@@ -245,11 +245,11 @@ void NotifyReadyToActivate() override; void NotifyReadyToDraw() override; void NotifyTileStateChanged(const Tile* tile) override; - void BuildRasterQueue(RasterTilePriorityQueue* queue, - TreePriority tree_priority, - RasterTilePriorityQueue::Type type) override; - void BuildEvictionQueue(EvictionTilePriorityQueue* queue, - TreePriority tree_priority) override; + scoped_ptr<RasterTilePriorityQueue> BuildRasterQueue( + TreePriority tree_priority, + RasterTilePriorityQueue::Type type) override; + scoped_ptr<EvictionTilePriorityQueue> BuildEvictionQueue( + TreePriority tree_priority) override; // ScrollbarAnimationControllerClient implementation. void PostDelayedScrollbarFade(const base::Closure& start_fade,
diff --git a/cc/trees/layer_tree_host_pixeltest_filters.cc b/cc/trees/layer_tree_host_pixeltest_filters.cc index dc8cc4a9..bf8e3e2 100644 --- a/cc/trees/layer_tree_host_pixeltest_filters.cc +++ b/cc/trees/layer_tree_host_pixeltest_filters.cc
@@ -283,7 +283,7 @@ gfx::Rect rect(50, 50, 100, 100); - static const int kInset = 3; + const int kInset = 3; for (int i = 0; !rect.IsEmpty(); ++i) { scoped_refptr<SolidColorLayer> layer = CreateSolidColorLayer(rect, (i & 1) ? SK_ColorWHITE : SK_ColorRED); @@ -334,6 +334,67 @@ base::FilePath(FILE_PATH_LITERAL("filter_on_scaled_layer.png"))); } +class ImageScaledRenderSurface : public LayerTreeHostFiltersPixelTest { + protected: + void RunPixelTestType(PixelTestType test_type, base::FilePath image_name) { + // A filter will cause a render surface to be used. Here we force the + // render surface on, and scale the result to make sure that we rasterize at + // the correct resolution. + scoped_refptr<SolidColorLayer> background = + CreateSolidColorLayer(gfx::Rect(300, 300), SK_ColorBLUE); + + scoped_refptr<SolidColorLayer> render_surface_layer = + CreateSolidColorLayer(gfx::Rect(0, 0, 200, 200), SK_ColorWHITE); + + gfx::Rect rect(50, 50, 100, 100); + + scoped_refptr<SolidColorLayer> child = + CreateSolidColorLayer(rect, SK_ColorRED); + + gfx::Transform transform; + transform.Translate(rect.width() / 2.0, rect.height() / 2.0); + transform.RotateAboutZAxis(30.0); + transform.Translate(-rect.width() / 2.0, -rect.height() / 2.0); + child->SetTransform(transform); + + render_surface_layer->AddChild(child); + + gfx::Transform render_surface_transform; + render_surface_transform.Scale(1.5f, 1.5f); + render_surface_layer->SetTransform(render_surface_transform); + render_surface_layer->SetForceRenderSurface(true); + + background->AddChild(render_surface_layer); + + // Software has some huge differences in the AA'd pixels on the different + // trybots. See crbug.com/452198. + float percentage_pixels_large_error = 0.686f; + float percentage_pixels_small_error = 0.0f; + float average_error_allowed_in_bad_pixels = 16.f; + int large_error_allowed = 17; + int small_error_allowed = 0; + pixel_comparator_.reset(new FuzzyPixelComparator( + true, // discard_alpha + percentage_pixels_large_error, percentage_pixels_small_error, + average_error_allowed_in_bad_pixels, large_error_allowed, + small_error_allowed)); + + RunPixelTest(test_type, background, image_name); + } +}; + +TEST_F(ImageScaledRenderSurface, ImageRenderSurfaceScaled_GL) { + RunPixelTestType( + PIXEL_TEST_GL, + base::FilePath(FILE_PATH_LITERAL("scaled_render_surface_layer_gl.png"))); +} + +TEST_F(ImageScaledRenderSurface, ImageRenderSurfaceScaled_Software) { + RunPixelTestType( + PIXEL_TEST_SOFTWARE, + base::FilePath(FILE_PATH_LITERAL("scaled_render_surface_layer_sw.png"))); +} + } // namespace } // namespace cc
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc index 8663e71..5299d70 100644 --- a/cc/trees/layer_tree_host_unittest.cc +++ b/cc/trees/layer_tree_host_unittest.cc
@@ -43,6 +43,7 @@ #include "cc/test/fake_scoped_ui_resource.h" #include "cc/test/fake_video_frame_provider.h" #include "cc/test/geometry_test_utils.h" +#include "cc/test/impl_side_painting_settings.h" #include "cc/test/layer_tree_test.h" #include "cc/test/test_shared_bitmap_manager.h" #include "cc/test/test_web_graphics_context_3d.h" @@ -5573,7 +5574,9 @@ pinch->SetIsContainerForFixedPositionLayers(true); root->AddChild(pinch); - scoped_ptr<FakePicturePile> pile(new FakePicturePile); + scoped_ptr<FakePicturePile> pile( + new FakePicturePile(ImplSidePaintingSettings().minimum_contents_scale, + ImplSidePaintingSettings().default_tile_grid_size)); pile->SetPlaybackAllowedEvent(&playback_allowed_event_); scoped_refptr<FakePictureLayer> layer = FakePictureLayer::CreateWithRecordingSource(&client_, pile.Pass()); @@ -5776,7 +5779,9 @@ scoped_refptr<Layer> root = Layer::Create(); root->SetBounds(gfx::Size(500, 500)); - scoped_ptr<FakePicturePile> pile(new FakePicturePile); + scoped_ptr<FakePicturePile> pile( + new FakePicturePile(ImplSidePaintingSettings().minimum_contents_scale, + ImplSidePaintingSettings().default_tile_grid_size)); scoped_refptr<FakePictureLayer> layer = FakePictureLayer::CreateWithRecordingSource(&client_, pile.Pass()); layer->SetBounds(gfx::Size(500, 500)); @@ -5816,7 +5821,9 @@ void SetupTree() override { client_.set_fill_with_nonsolid_color(true); - scoped_ptr<FakePicturePile> pile(new FakePicturePile); + scoped_ptr<FakePicturePile> pile( + new FakePicturePile(ImplSidePaintingSettings().minimum_contents_scale, + ImplSidePaintingSettings().default_tile_grid_size)); scoped_refptr<FakePictureLayer> root = FakePictureLayer::CreateWithRecordingSource(&client_, pile.Pass()); root->SetBounds(gfx::Size(viewport_size_.width(), 10000)); @@ -5836,12 +5843,11 @@ // Verify which tiles got resources using an eviction iterator, which has to // return all tiles that have resources. - EvictionTilePriorityQueue eviction_queue; - host_impl->BuildEvictionQueue(&eviction_queue, - SAME_PRIORITY_FOR_BOTH_TREES); + scoped_ptr<EvictionTilePriorityQueue> eviction_queue( + host_impl->BuildEvictionQueue(SAME_PRIORITY_FOR_BOTH_TREES)); int tile_count = 0; - for (; !eviction_queue.IsEmpty(); eviction_queue.Pop()) { - Tile* tile = eviction_queue.Top(); + for (; !eviction_queue->IsEmpty(); eviction_queue->Pop()) { + Tile* tile = eviction_queue->Top(); // Ensure this tile is within the viewport. EXPECT_TRUE(tile->content_rect().Intersects(gfx::Rect(viewport_size_))); // Ensure that the tile is 1/4 of the viewport tall (plus padding). @@ -5887,7 +5893,9 @@ pinch->SetIsContainerForFixedPositionLayers(true); root->AddChild(pinch); - scoped_ptr<FakePicturePile> pile(new FakePicturePile); + scoped_ptr<FakePicturePile> pile( + new FakePicturePile(ImplSidePaintingSettings().minimum_contents_scale, + ImplSidePaintingSettings().default_tile_grid_size)); pile->SetPlaybackAllowedEvent(&playback_allowed_event_); scoped_refptr<FakePictureLayer> layer = FakePictureLayer::CreateWithRecordingSource(&client_, pile.Pass());
diff --git a/cc/trees/proxy_timing_history.cc b/cc/trees/proxy_timing_history.cc index 9020ad5..90abad1 100644 --- a/cc/trees/proxy_timing_history.cc +++ b/cc/trees/proxy_timing_history.cc
@@ -43,11 +43,11 @@ } void ProxyTimingHistory::DidBeginMainFrame() { - begin_main_frame_sent_time_ = base::TimeTicks::HighResNow(); + begin_main_frame_sent_time_ = base::TimeTicks::Now(); } void ProxyTimingHistory::DidCommit() { - commit_complete_time_ = base::TimeTicks::HighResNow(); + commit_complete_time_ = base::TimeTicks::Now(); base::TimeDelta begin_main_frame_to_commit_duration = commit_complete_time_ - begin_main_frame_sent_time_; @@ -64,7 +64,7 @@ void ProxyTimingHistory::DidActivateSyncTree() { base::TimeDelta commit_to_activate_duration = - base::TimeTicks::HighResNow() - commit_complete_time_; + base::TimeTicks::Now() - commit_complete_time_; // Before adding the new data point to the timing history, see what we would // have predicted for this frame. This allows us to keep track of the accuracy @@ -77,12 +77,11 @@ } void ProxyTimingHistory::DidStartDrawing() { - start_draw_time_ = base::TimeTicks::HighResNow(); + start_draw_time_ = base::TimeTicks::Now(); } void ProxyTimingHistory::DidFinishDrawing() { - base::TimeDelta draw_duration = - base::TimeTicks::HighResNow() - start_draw_time_; + base::TimeDelta draw_duration = base::TimeTicks::Now() - start_draw_time_; // Before adding the new data point to the timing history, see what we would // have predicted for this frame. This allows us to keep track of the accuracy
diff --git a/cc/trees/single_thread_proxy.cc b/cc/trees/single_thread_proxy.cc index e29f0d1..83e6bbed 100644 --- a/cc/trees/single_thread_proxy.cc +++ b/cc/trees/single_thread_proxy.cc
@@ -484,14 +484,15 @@ } void SingleThreadProxy::DidSwapBuffersCompleteOnImplThread() { - TRACE_EVENT0("cc", "SingleThreadProxy::DidSwapBuffersCompleteOnImplThread"); + TRACE_EVENT0("cc,benchmark", + "SingleThreadProxy::DidSwapBuffersCompleteOnImplThread"); if (scheduler_on_impl_thread_) scheduler_on_impl_thread_->DidSwapBuffersComplete(); layer_tree_host_->DidCompleteSwapBuffers(); } void SingleThreadProxy::CompositeImmediately(base::TimeTicks frame_begin_time) { - TRACE_EVENT0("cc", "SingleThreadProxy::CompositeImmediately"); + TRACE_EVENT0("cc,benchmark", "SingleThreadProxy::CompositeImmediately"); DCHECK(Proxy::IsMainThread()); base::AutoReset<bool> inside_composite(&inside_synchronous_composite_, true);
diff --git a/cc/trees/thread_proxy.cc b/cc/trees/thread_proxy.cc index 4b360a4..329b3e8 100644 --- a/cc/trees/thread_proxy.cc +++ b/cc/trees/thread_proxy.cc
@@ -349,7 +349,8 @@ } void ThreadProxy::DidSwapBuffersCompleteOnImplThread() { - TRACE_EVENT0("cc", "ThreadProxy::DidSwapBuffersCompleteOnImplThread"); + TRACE_EVENT0("cc,benchmark", + "ThreadProxy::DidSwapBuffersCompleteOnImplThread"); DCHECK(IsImplThread()); impl().scheduler->DidSwapBuffersComplete(); Proxy::MainThreadTaskRunner()->PostTask(
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn index c9d20a9..b1fd8a7 100644 --- a/chrome/BUILD.gn +++ b/chrome/BUILD.gn
@@ -141,13 +141,12 @@ # Chromium functionality into this .dll. #'chrome_version_resources', TODO(GYP) "//chrome/app/theme:chrome_unscaled_resources", + "//chrome_elf", "//content/app/resources", "//crypto", "//net:net_resources", "//third_party/wtl", "//ui/views", - - #'<(DEPTH)/chrome_elf/chrome_elf.gyp:chrome_elf' ] TODO(GYP) ] if (enable_configuration_policy) { deps += [ "//components/policy" ]
diff --git a/chrome/DEPS b/chrome/DEPS index 923e17b..9c95992 100644 --- a/chrome/DEPS +++ b/chrome/DEPS
@@ -23,7 +23,6 @@ "+content/public/common", "+content/public/test", "+mojo/common", - "+mojo/public", # Don't allow inclusion of these other libs we shouldn't be calling directly. "-webkit", @@ -38,6 +37,7 @@ # Allow inclusion of third-party code: "+third_party/hunspell", "+third_party/libxml", + "+third_party/mojo/src/mojo/public", "+third_party/skia", "+ui",
diff --git a/chrome/VERSION b/chrome/VERSION index 9cf3adeb..2b899ee3 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=42 MINOR=0 -BUILD=2285 +BUILD=2289 PATCH=0
diff --git a/chrome/android/java/DEPS b/chrome/android/java/DEPS index 590314b..8ee9f07 100644 --- a/chrome/android/java/DEPS +++ b/chrome/android/java/DEPS
@@ -4,7 +4,5 @@ "+components/bookmarks/common/android/java/src/org/chromium/components/bookmarks", "+components/dom_distiller/android/java/src/org/chromium/components/dom_distiller/core", "+content/public/android/java", - "+sync/android/java/src/org/chromium/sync/internal_api/pub", - "+sync/android/java/src/org/chromium/sync/notifier", - "+sync/android/java/src/org/chromium/sync/signin", + "+sync/android/java/src/org/chromium/sync", ]
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeBrowserProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeBrowserProvider.java index 59fd08d6..860c2ab 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeBrowserProvider.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeBrowserProvider.java
@@ -35,7 +35,7 @@ import org.chromium.base.VisibleForTesting; import org.chromium.base.annotations.SuppressFBWarnings; import org.chromium.chrome.browser.database.SQLiteCursor; -import org.chromium.sync.notifier.SyncStatusHelper; +import org.chromium.sync.AndroidSyncSettings; import java.util.ArrayList; import java.util.Arrays; @@ -630,7 +630,7 @@ // Don't allow going up the hierarchy if sync is disabled and the requested node // is the Mobile Bookmarks folder. if (getParent && nodeId == getMobileBookmarksFolderId() - && !SyncStatusHelper.get(getContext()).isSyncEnabled()) { + && !AndroidSyncSettings.get(getContext()).isSyncEnabled()) { getParent = false; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/Tab.java b/chrome/android/java/src/org/chromium/chrome/browser/Tab.java index d80a655..2a5b6e75 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/Tab.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/Tab.java
@@ -762,7 +762,7 @@ // TODO(ppi): Should we pass Referrer jobject and add JNI methods to read it // from the native? params.getReferrer() != null ? params.getReferrer().getPolicy() : 0, - params.getIsRendererInitiated()); + params.getIsRendererInitiated(), params.getIntentReceivedTimestamp()); for (TabObserver observer : mObservers) { observer.onLoadUrl(this, params.getUrl(), loadType); @@ -2371,7 +2371,7 @@ private native Profile nativeGetProfileAndroid(long nativeTabAndroid); private native int nativeLoadUrl(long nativeTabAndroid, String url, String extraHeaders, byte[] postData, int transition, String referrerUrl, int referrerPolicy, - boolean isRendererInitiated); + boolean isRendererInitiated, long intentReceivedTimestamp); private native void nativeSetActiveNavigationEntryTitleForUrl(long nativeTabAndroid, String url, String title); private native boolean nativePrint(long nativeTabAndroid);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/invalidation/InvalidationController.java b/chrome/android/java/src/org/chromium/chrome/browser/invalidation/InvalidationController.java index 3f953b7..5e19e2a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/invalidation/InvalidationController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/invalidation/InvalidationController.java
@@ -12,10 +12,10 @@ import org.chromium.base.ApplicationStatus; import org.chromium.base.VisibleForTesting; import org.chromium.components.invalidation.InvalidationClientService; +import org.chromium.sync.AndroidSyncSettings; import org.chromium.sync.internal_api.pub.base.ModelType; import org.chromium.sync.notifier.InvalidationIntentProtocol; import org.chromium.sync.notifier.InvalidationPreferences; -import org.chromium.sync.notifier.SyncStatusHelper; import java.util.Set; @@ -55,8 +55,8 @@ InvalidationPreferences invalidationPreferences = new InvalidationPreferences(mContext); Set<String> savedSyncedTypes = invalidationPreferences.getSavedSyncedTypes(); Account account = invalidationPreferences.getSavedSyncedAccount(); - boolean allTypes = savedSyncedTypes != null && - savedSyncedTypes.contains(ModelType.ALL_TYPES_TYPE); + boolean allTypes = savedSyncedTypes != null + && savedSyncedTypes.contains(ModelType.ALL_TYPES_TYPE); setRegisteredTypes(account, allTypes, types); } @@ -104,7 +104,7 @@ @Override public void onApplicationStateChange(int newState) { - if (SyncStatusHelper.get(mContext).isSyncEnabled()) { + if (AndroidSyncSettings.get(mContext).isSyncEnabled()) { if (newState == ApplicationState.HAS_RUNNING_ACTIVITIES) { start(); } else if (newState == ApplicationState.HAS_PAUSED_ACTIVITIES) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java index 6723fc9a..2a5c4bbbf 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java
@@ -26,8 +26,8 @@ import org.chromium.chrome.R; import org.chromium.chrome.browser.invalidation.InvalidationController; import org.chromium.chrome.browser.sync.ProfileSyncService; +import org.chromium.sync.AndroidSyncSettings; import org.chromium.sync.internal_api.pub.base.ModelType; -import org.chromium.sync.notifier.SyncStatusHelper; import org.chromium.sync.signin.ChromeSigninController; import java.util.HashSet; @@ -371,7 +371,7 @@ // Sign-in to sync. ProfileSyncService profileSyncService = ProfileSyncService.get(mContext); - if (SyncStatusHelper.get(mContext).isSyncEnabled(mSignInAccount) + if (AndroidSyncSettings.get(mContext).isSyncEnabled(mSignInAccount) && !profileSyncService.hasSyncSetupCompleted()) { profileSyncService.setSetupInProgress(true); profileSyncService.syncSignIn(); @@ -454,8 +454,10 @@ nativeWipeProfileData(mNativeSigninManagerAndroid); } - // This class must be public and static. Otherwise an exception will be thrown when Android - // recreates the fragment (e.g. after a configuration change). + /** + * This class must be public and static. Otherwise an exception will be thrown when Android + * recreates the fragment (e.g. after a configuration change). + */ public static class ClearDataProgressDialog extends DialogFragment { @Override public void onCreate(Bundle savedInstanceState) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/DelayedSyncController.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/DelayedSyncController.java index c71d473..b5b21ee 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/sync/DelayedSyncController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/DelayedSyncController.java
@@ -15,7 +15,7 @@ import org.chromium.base.ApplicationStatus; import org.chromium.base.VisibleForTesting; -import org.chromium.sync.notifier.SyncStatusHelper; +import org.chromium.sync.AndroidSyncSettings; import org.chromium.sync.signin.AccountManagerHelper; /** @@ -64,7 +64,7 @@ @Override protected Void doInBackground(Void... unused) { String contractAuthority = - SyncStatusHelper.get(context).getContractAuthority(); + AndroidSyncSettings.get(context).getContractAuthority(); ContentResolver.requestSync(account, contractAuthority, new Bundle()); return null; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/SyncController.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/SyncController.java index df67f95..55664d7 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/sync/SyncController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/SyncController.java
@@ -13,7 +13,7 @@ import org.chromium.chrome.browser.invalidation.InvalidationController; import org.chromium.chrome.browser.signin.SigninManager; import org.chromium.chrome.browser.signin.SigninManager.SignInFlowObserver; -import org.chromium.sync.notifier.SyncStatusHelper; +import org.chromium.sync.AndroidSyncSettings; import org.chromium.sync.signin.AccountManagerHelper; import org.chromium.sync.signin.ChromeSigninController; @@ -33,21 +33,21 @@ * on when it is re-enabled. */ public class SyncController implements ProfileSyncService.SyncStateChangedListener, - SyncStatusHelper.SyncSettingsChangedObserver { + AndroidSyncSettings.AndroidSyncSettingsObserver { private static final String TAG = "SyncController"; private static SyncController sInstance; private final Context mContext; private final ChromeSigninController mChromeSigninController; - private final SyncStatusHelper mSyncStatusHelper; + private final AndroidSyncSettings mAndroidSyncSettings; private final ProfileSyncService mProfileSyncService; private SyncController(Context context) { mContext = context; mChromeSigninController = ChromeSigninController.get(mContext); - mSyncStatusHelper = SyncStatusHelper.get(context); - mSyncStatusHelper.registerSyncSettingsChangedObserver(this); + mAndroidSyncSettings = AndroidSyncSettings.get(context); + mAndroidSyncSettings.registerObserver(this); mProfileSyncService = ProfileSyncService.get(mContext); mProfileSyncService.addSyncStateChangedListener(this); mChromeSigninController.ensureGcmIsInitialized(); @@ -104,7 +104,7 @@ * Updates sync to reflect the state of the Android sync settings. */ public void updateSyncStateFromAndroid() { - if (mSyncStatusHelper.isSyncEnabled()) { + if (mAndroidSyncSettings.isSyncEnabled()) { start(); } else { stop(); @@ -118,12 +118,12 @@ */ public void start() { ThreadUtils.assertOnUiThread(); - if (mSyncStatusHelper.isMasterSyncAutomaticallyEnabled()) { + if (mAndroidSyncSettings.isMasterSyncEnabled()) { Log.d(TAG, "Enabling sync"); Account account = mChromeSigninController.getSignedInUser(); InvalidationController.get(mContext).start(); mProfileSyncService.enableSync(); - mSyncStatusHelper.enableAndroidSync(account); + mAndroidSyncSettings.enableChromeSync(account); } } @@ -139,11 +139,11 @@ Account account = mChromeSigninController.getSignedInUser(); InvalidationController.get(mContext).stop(); mProfileSyncService.disableSync(); - if (mSyncStatusHelper.isMasterSyncAutomaticallyEnabled()) { + if (mAndroidSyncSettings.isMasterSyncEnabled()) { // Only disable Android's Chrome sync setting if we weren't disabled // by the master sync setting. This way, when master sync is enabled // they will both be on and sync will start again. - mSyncStatusHelper.disableAndroidSync(account); + mAndroidSyncSettings.disableChromeSync(account); } } } @@ -164,21 +164,21 @@ // Make the Java state match the native state. if (isSyncActive) { InvalidationController.get(mContext).start(); - mSyncStatusHelper.enableAndroidSync(account); + mAndroidSyncSettings.enableChromeSync(account); } else { InvalidationController.get(mContext).stop(); - if (mSyncStatusHelper.isMasterSyncAutomaticallyEnabled()) { + if (mAndroidSyncSettings.isMasterSyncEnabled()) { // See comment in stop(). - mSyncStatusHelper.disableAndroidSync(account); + mAndroidSyncSettings.disableChromeSync(account); } } } /** - * From {@link SyncStatusHelper.SyncSettingsChangedObserver}. + * From {@link AndroidSyncSettings.AndroidSyncSettingsObserver}. */ @Override - public void syncSettingsChanged() { + public void androidSyncSettingsChanged() { ThreadUtils.runOnUiThread(new Runnable() { @Override public void run() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/SyncNotificationController.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/SyncNotificationController.java index 4b561c7..7181960a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/sync/SyncNotificationController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/SyncNotificationController.java
@@ -17,6 +17,7 @@ import org.chromium.chrome.browser.notifications.GoogleServicesNotificationController; import org.chromium.chrome.browser.notifications.NotificationConstants; import org.chromium.chrome.browser.preferences.PreferencesLauncher; +import org.chromium.sync.AndroidSyncSettings; import org.chromium.sync.notifier.SyncStatusHelper; /** @@ -27,19 +28,35 @@ private static final String TAG = "SyncNotificationController"; private final Context mApplicationContext; private final GoogleServicesNotificationController mNotificationController; - private final SyncStatusHelper mSyncStatusHelper; + private final AndroidSyncSettings mAndroidSyncSettings; private final Class<? extends Activity> mPassphraseRequestActivity; private final Class<? extends Fragment> mAccountManagementFragment; private final ProfileSyncService mProfileSyncService; public SyncNotificationController(Context context, + GoogleServicesNotificationController controller, + Class<? extends Activity> passphraseRequestActivity, + Class<? extends Fragment> accountManagementFragment) { + mApplicationContext = context.getApplicationContext(); + mNotificationController = controller; + mProfileSyncService = ProfileSyncService.get(context); + mAndroidSyncSettings = AndroidSyncSettings.get(context); + mPassphraseRequestActivity = passphraseRequestActivity; + mAccountManagementFragment = accountManagementFragment; + } + + /** + * Deprecated for having unnecessary args; use the first constructor. + */ + @Deprecated + public SyncNotificationController(Context context, GoogleServicesNotificationController controller, ProfileSyncService profileSyncService, SyncStatusHelper syncStatusHelper, Class<? extends Activity> passphraseRequestActivity, Class<? extends Fragment> accountManagementFragment) { mApplicationContext = context.getApplicationContext(); mNotificationController = controller; mProfileSyncService = profileSyncService; - mSyncStatusHelper = syncStatusHelper; + mAndroidSyncSettings = AndroidSyncSettings.get(context); mPassphraseRequestActivity = passphraseRequestActivity; mAccountManagementFragment = accountManagementFragment; } @@ -63,7 +80,7 @@ Intent intent; // Auth errors take precedence over passphrase errors. - if (!mSyncStatusHelper.isSyncEnabled()) { + if (!mAndroidSyncSettings.isSyncEnabled()) { mNotificationController.cancelNotification(NotificationConstants.NOTIFICATION_ID_SYNC); return; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/ChromeSwitchCompat.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/ChromeSwitchCompat.java index 3a98cb6e..fe6526b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/widget/ChromeSwitchCompat.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/ChromeSwitchCompat.java
@@ -18,6 +18,8 @@ * TalkBack doesn't recognize the SwitchCompat class, so it reads events with that classname as * "Checkbox". This works around the bug by marking accessibility events from SwitchCompat with the * Switch class name, which TalkBack recognizes. + * + * TODO(newt): Delete this class once the support library is fixed. http://b/19110477 */ public class ChromeSwitchCompat extends SwitchCompat {
diff --git a/chrome/android/javatests/DEPS b/chrome/android/javatests/DEPS index c3995586..6827256b 100644 --- a/chrome/android/javatests/DEPS +++ b/chrome/android/javatests/DEPS
@@ -2,9 +2,7 @@ "+components/dom_distiller/android/java/src/org/chromium/components/dom_distiller/core", "+components/bookmarks/common/android/java/src/org/chromium/components/bookmarks", "+content/public/android/java", - "+sync/android/java/src/org/chromium/sync/internal_api/pub", - "+sync/android/java/src/org/chromium/sync/notifier", - "+sync/android/java/src/org/chromium/sync/signin", + "+sync/android/java/src/org/chromium/sync", # We should only depend on the util package of something that lives in # javatests. "+sync/test/android/javatests/src/org/chromium/sync/test/util",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/invalidation/InvalidationControllerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/invalidation/InvalidationControllerTest.java index 3d86284..0692c39 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/invalidation/InvalidationControllerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/invalidation/InvalidationControllerTest.java
@@ -16,10 +16,10 @@ import org.chromium.base.CollectionUtil; import org.chromium.base.test.util.Feature; import org.chromium.components.invalidation.InvalidationClientService; +import org.chromium.sync.AndroidSyncSettings; import org.chromium.sync.internal_api.pub.base.ModelType; import org.chromium.sync.notifier.InvalidationIntentProtocol; import org.chromium.sync.notifier.InvalidationPreferences; -import org.chromium.sync.notifier.SyncStatusHelper; import org.chromium.sync.signin.AccountManagerHelper; import org.chromium.sync.signin.ChromeSigninController; import org.chromium.sync.test.util.MockSyncContentResolverDelegate; @@ -46,7 +46,7 @@ MockSyncContentResolverDelegate delegate = new MockSyncContentResolverDelegate(); // Android master sync can safely always be on. delegate.setMasterSyncAutomatically(true); - SyncStatusHelper.overrideSyncStatusHelperForTests(mContext, delegate); + AndroidSyncSettings.overrideAndroidSyncSettingsForTests(mContext, delegate); } @SmallTest @@ -117,11 +117,11 @@ Account account = AccountManagerHelper.createAccountFromName("test@gmail.com"); ChromeSigninController chromeSigninController = ChromeSigninController.get(mContext); chromeSigninController.setSignedInAccountName(account.name); - SyncStatusHelper syncStatusHelper = SyncStatusHelper.get(mContext); + AndroidSyncSettings androidSyncSettings = AndroidSyncSettings.get(mContext); if (syncEnabled) { - syncStatusHelper.enableAndroidSync(account); + androidSyncSettings.enableChromeSync(account); } else { - syncStatusHelper.disableAndroidSync(account); + androidSyncSettings.disableChromeSync(account); } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/invalidation/InvalidationServiceTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/invalidation/InvalidationServiceTest.java index 884b100..8fa1c2ef 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/invalidation/InvalidationServiceTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/invalidation/InvalidationServiceTest.java
@@ -14,9 +14,9 @@ import org.chromium.chrome.shell.ChromeShellTestBase; import org.chromium.components.invalidation.InvalidationClientService; import org.chromium.components.invalidation.InvalidationService; +import org.chromium.sync.AndroidSyncSettings; import org.chromium.sync.internal_api.pub.base.ModelType; import org.chromium.sync.notifier.InvalidationIntentProtocol; -import org.chromium.sync.notifier.SyncStatusHelper; import org.chromium.sync.test.util.MockSyncContentResolverDelegate; import java.util.Set; @@ -36,7 +36,7 @@ MockSyncContentResolverDelegate delegate = new MockSyncContentResolverDelegate(); // Android master sync can safely always be on. delegate.setMasterSyncAutomatically(true); - SyncStatusHelper.overrideSyncStatusHelperForTests(mContext, delegate); + AndroidSyncSettings.overrideAndroidSyncSettingsForTests(mContext, delegate); } @SmallTest
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ChromiumSyncAdapterTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ChromiumSyncAdapterTest.java index fb84f98..dc863ddd 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ChromiumSyncAdapterTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ChromiumSyncAdapterTest.java
@@ -17,7 +17,7 @@ import org.chromium.base.CommandLine; import org.chromium.base.test.util.Feature; import org.chromium.chrome.shell.ChromeShellTestBase; -import org.chromium.sync.notifier.SyncStatusHelper; +import org.chromium.sync.AndroidSyncSettings; import org.chromium.sync.signin.AccountManagerHelper; /** @@ -72,7 +72,7 @@ public void performSyncWithBundle(Bundle bundle) { mSyncAdapter.onPerformSync(TEST_ACCOUNT, bundle, - SyncStatusHelper.get(getActivity()).getContractAuthority(), + AndroidSyncSettings.get(getActivity()).getContractAuthority(), null, new SyncResult()); }
diff --git a/chrome/android/sync_shell/javatests/DEPS b/chrome/android/sync_shell/javatests/DEPS index 0f4fab0..036906f 100644 --- a/chrome/android/sync_shell/javatests/DEPS +++ b/chrome/android/sync_shell/javatests/DEPS
@@ -1,6 +1,5 @@ include_rules = [ "+content/public/android/java", - "+sync/android/java/src/org/chromium/sync/notifier", - "+sync/android/java/src/org/chromium/sync/signin", + "+sync/android/java/src/org/chromium/sync", "+sync/test/android/javatests/src/org/chromium/sync/test/util", ]
diff --git a/chrome/android/sync_shell/javatests/src/chromium/chrome/browser/sync/SyncTest.java b/chrome/android/sync_shell/javatests/src/chromium/chrome/browser/sync/SyncTest.java index 9c6db59..4386426 100644 --- a/chrome/android/sync_shell/javatests/src/chromium/chrome/browser/sync/SyncTest.java +++ b/chrome/android/sync_shell/javatests/src/chromium/chrome/browser/sync/SyncTest.java
@@ -23,7 +23,7 @@ import org.chromium.content.browser.test.util.Criteria; import org.chromium.content.browser.test.util.CriteriaHelper; import org.chromium.content.browser.test.util.JavaScriptUtils; -import org.chromium.sync.notifier.SyncStatusHelper; +import org.chromium.sync.AndroidSyncSettings; import org.chromium.sync.signin.AccountManagerHelper; import org.chromium.sync.signin.ChromeSigninController; import org.chromium.sync.test.util.MockAccountManager; @@ -57,7 +57,8 @@ MockSyncContentResolverDelegate syncContentResolverDelegate = new MockSyncContentResolverDelegate(); syncContentResolverDelegate.setMasterSyncAutomatically(true); - SyncStatusHelper.overrideSyncStatusHelperForTests(mContext, syncContentResolverDelegate); + AndroidSyncSettings.overrideAndroidSyncSettingsForTests( + mContext, syncContentResolverDelegate); // This call initializes the ChromeSigninController to use our test context. ChromeSigninController.get(mContext); startChromeBrowserProcessSync(getInstrumentation().getTargetContext()); @@ -171,11 +172,11 @@ AccountManagerHelper.createAccountFromName(SyncTestUtil.DEFAULT_TEST_ACCOUNT); // Disabling Android sync should turn Chrome sync engine off. - SyncStatusHelper.get(mContext).disableAndroidSync(account); + AndroidSyncSettings.get(mContext).disableChromeSync(account); SyncTestUtil.verifySyncIsDisabled(mContext, account); // Enabling Android sync should turn Chrome sync engine on. - SyncStatusHelper.get(mContext).enableAndroidSync(account); + AndroidSyncSettings.get(mContext).enableChromeSync(account); SyncTestUtil.ensureSyncInitialized(mContext); SyncTestUtil.verifySignedInWithAccount(mContext, account); }
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp index 712c00b..d62db65 100644 --- a/chrome/app/chromeos_strings.grdp +++ b/chrome/app/chromeos_strings.grdp
@@ -1760,6 +1760,9 @@ <message name="IDS_OFFLINE_LOGIN_HTML" desc="Text which suggests enter as an existing user when valid network isn't presented."> If you've already registered on this device, you can <ph name="LINK2_START">$1<ex>>a<</ex></ph>sign in as an existing user<ph name="LINK2_END">$2<ex>>/a<</ex></ph>. </message> + <message name="IDS_RESTART_BUTTON" desc="Text shown on reboot button on login/locker screen"> + Restart + </message> <message name="IDS_SHUTDOWN_BUTTON" desc="Text shown on shutdown button on login/locker screen"> Shut down </message> @@ -5341,7 +5344,7 @@ The Files app provides quick access to files that you've saved on Google Drive, external storage, or your Chrome OS device. </message> - <!-- HDCP verification UI --> + <!-- Platform verification UI --> <message name="IDS_PLATFORM_VERIFICATION_DIALOG_HEADLINE" desc="The label to describe what the dialog wants to confirm."> <ph name="DOMAIN">$1<ex>example.com</ex></ph> requires your device's identity to be verified, by Google, to determine eligibility for enhanced playback of protected media. <ph name="LEARN_MORE">$2<ex>Learn more</ex></ph>. </message>
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 4b2cc75..8d93e961 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -450,6 +450,9 @@ <message name="IDS_PERMISSION_ALLOW" desc="Label on button to allow a permissions request."> Allow </message> + <message name="IDS_PERMISSION_ALLOW_COMBOBOX" desc="Label on combobox to allow the user to either allow all or customize."> + Allow all or customize + </message> <message name="IDS_PERMISSION_DENY" desc="Label on button to deny a permissions request."> Block </message> @@ -2185,8 +2188,8 @@ Add shortcut? </message> - <message name="IDS_BOOKMARK_APP_BUBBLE_OPEN_AS_TAB" desc="Checkbox text for opening the bookmark app as a tab."> - Open as tab + <message name="IDS_BOOKMARK_APP_BUBBLE_OPEN_AS_WINDOW" desc="Checkbox text for opening the bookmark app as a window."> + Open as window </message> <!-- Quit all apps confirmation dialog --> @@ -5558,7 +5561,7 @@ Enable </message> <message name="IDS_PLUGINS_ALWAYS_ALLOWED" desc="The checkbox label for whitelisting a plug-in for content settings."> - Always allowed + Always allowed to run </message> <message name="IDS_PLUGINS_DOWNLOAD" desc="The link label to download the latest version of this plug-in"> Download Critical Security Update @@ -5674,6 +5677,21 @@ <message name="IDS_NACL_DEBUG_MASK_CHOICE_INCLUDE_DEBUG"> Debug only if manifest URL ends with debug.nmf. </message> + <message name="IDS_MARK_NON_SECURE_AS_NAME" desc="Name of the 'Mark Non-Secure Origins As' lab."> + Mark non-secure origins as non-secure + </message> + <message name="IDS_MARK_NON_SECURE_AS_DESCRIPTION" desc="Description of the 'Mark Non-Secure Origins As' lab."> + Mark non-secure origins as non-secure, or as "dubious". + </message> + <message name="IDS_MARK_NON_SECURE_AS_NEUTRAL"> + Mark non-secure origins as neutral. + </message> + <message name="IDS_MARK_NON_SECURE_AS_NON_SECURE"> + Mark non-secure origins as non-secure. + </message> + <message name="IDS_MARK_NON_SECURE_AS_DUBIOUS"> + Mark non-secure origins as dubious. + </message> <message name="IDS_FLAGS_SAVE_PAGE_AS_MHTML_NAME" desc="Name of the 'Save Page as MHTML' lab."> Save Page as MHTML </message> @@ -6021,11 +6039,11 @@ <message name="IDS_FLAGS_DISABLE_MEDIA_SOURCE_DESCRIPTION" desc="Description for the flag to disable the Media Source API."> Disable the MediaSource object. This object allows JavaScript to send media data directly to a video element. </message> - <message name="IDS_FLAGS_ENABLE_ENCRYPTED_MEDIA_NAME" desc="Title for the flag to enable the (unprefixed) Encrypted Media Extensions APIs (e.g. MediaKeys)."> - Enable Encrypted Media Extensions. + <message name="IDS_FLAGS_DISABLE_ENCRYPTED_MEDIA_NAME" desc="Title for the flag to disable the Encrypted Media Extensions APIs."> + Disable Encrypted Media Extensions. </message> - <message name="IDS_FLAGS_ENABLE_ENCRYPTED_MEDIA_DESCRIPTION" desc="Description for the flag to enable the (unprefixed) Encrypted Media Extensions APIs (e.g. MediaKeys)."> - Enable Encrypted Media Extensions on video and audio elements. This enables the latest version of the Encrypted Media Extensions. + <message name="IDS_FLAGS_DISABLE_ENCRYPTED_MEDIA_DESCRIPTION" desc="Description for the flag to disable the Encrypted Media Extensions APIs."> + Disable Encrypted Media Extensions on video and audio elements. </message> <message name="IDS_FLAGS_DISABLE_PREFIXED_ENCRYPTED_MEDIA_NAME" desc="Title for the flag to disable the prefixed Encrypted Media Extensions APIs (e.g. webkitGenerateKeyRequest())."> Disable prefixed Encrypted Media Extensions. @@ -6379,12 +6397,6 @@ Enable or disable using the development version of the data reduction proxy. </message> </if> - <message name="IDS_FLAGS_IMPL_SIDE_PAINTING_NAME" desc="Name of about:flags option for impl-side painting."> - Impl-side painting - </message> - <message name="IDS_FLAGS_IMPL_SIDE_PAINTING_DESCRIPTION" desc="Description of about:flags option for impl-side painting."> - If enabled, painting is done on a separate thread instead of the main thread. - </message> <message name="IDS_FLAGS_LCD_TEXT_NAME" desc="Name of about:flags option for LCD text."> LCD text antialiasing </message> @@ -6529,12 +6541,6 @@ <message name="IDS_FLAGS_ENABLE_APP_LIST_DESCRIPTION" desc="Description of the flag to enable app launcher."> Enable the App Launcher. Upon enabling, creates operating system shortcuts to the App Launcher. </message> - <message name="IDS_FLAGS_DISABLE_APP_INFO_IN_APP_LIST" desc="Name of the flag to disable the app info context menu option in the app list."> - Disable the app info dialog. - </message> - <message name="IDS_FLAGS_DISABLE_APP_INFO_IN_APP_LIST_DESCRIPTION" desc="Description of the flag to disable the app info context menu option in the app list."> - Disable the app info dialog. If not disabled, the user will be able to select the 'App Info' context menu in the App Launcher to show the app info dialog for the selected app. - </message> <message name="IDS_FLAGS_ENABLE_EXPERIMENTAL_APP_LIST_NAME" desc="Name of the flag to enable the experimental app launcher."> Enable the experimental App Launcher. </message> @@ -8072,10 +8078,10 @@ Click to play </message> <message name="IDS_PLUGIN_BLOCK_RADIO" desc="A radio button in the Content Settings dialog for gating plug-ins on a context menu activation."> - Do not run plugins by default + Let me choose when to run plugin content </message> - <message name="IDS_PLUGIN_SELECTIVE_DISABLE" desc="Link to selectively disable plug-ins"> - Disable individual plug-ins... + <message name="IDS_PLUGIN_MANAGE_INDIVIDUAL" desc="Link to manage individual plug-ins"> + Manage individual plug-ins... </message> <message name="IDS_JAVASCRIPT_TAB_LABEL" desc="Label for JavaScript tab on Content Settings dialog"> JavaScript @@ -9901,6 +9907,9 @@ Connect to network </message> <message name="IDS_CAPTIVE_PORTAL_PRIMARY_PARAGRAPH" desc="The primary explanatory paragraph for the captive portal error page for network connections."> + The network you are using may require you to visit <ph name="BEGIN_BOLD"><strong></ph><ph name="LOGIN_URL">$1<ex>example.com</ex></ph><ph name="END_BOLD"><strong></ph>. + </message> + <message name="IDS_CAPTIVE_PORTAL_PRIMARY_PARAGRAPH_NO_LOGIN_URL" desc="The primary explanatory paragraph for the captive portal error page for network connections when the captive portal login url isn't available."> The network you are using may require you to visit its login page. </message> <message name="IDS_CAPTIVE_PORTAL_BUTTON_OPEN_LOGIN_PAGE" desc="Text for the open login page button"> @@ -11050,6 +11059,12 @@ <message name="IDS_AUTOFILL_CARD_UNMASK_PROMPT_INSTRUCTIONS_AMEX" desc="Text explaining what the user should do in the card unmasking dialog for amex cards."> Enter the four digit verification code from the front of your credit card </message> + <message name="IDS_AUTOFILL_CARD_UNMASK_PROMPT_INSTRUCTIONS_EXPIRED" desc="Text explaining what the user should do in the card unmasking dialog to update an expired card."> + Enter the expiration date and three digit verification code from the back of your credit card + </message> + <message name="IDS_AUTOFILL_CARD_UNMASK_PROMPT_INSTRUCTIONS_EXPIRED_AMEX" desc="Text explaining what the user should do in the card unmasking dialog to update an expired amex card."> + Enter the expiration date and four digit verification code from the front of your credit card + </message> <message name="IDS_APPEARANCE_GROUP_NAME" desc="The title of the appearance group"> Appearance @@ -14709,12 +14724,6 @@ <!-- Local Device Discovery display strings --> <if expr="enable_service_discovery"> - <message name="IDS_FLAGS_ENABLE_CLOUD_DEVICES_NAME" desc="Name of the 'Enable Cloud Devices' lab."> - Enable Google Cloud Devices - </message> - <message name="IDS_FLAGS_ENABLE_CLOUD_DEVICES_DESCRIPTION" desc="Description of the 'Enable Cloud Devices' lab."> - Enabled Google Cloud Devices features. - </message> <message name="IDS_LOCAL_DISCOVERY_SERVICE_REGISTER" desc="Name for button to register device in the Cloud"> Register </message>
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 765ab79..6ef8d02 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -648,15 +648,15 @@ deps += [ "//chrome:version_header", "//chrome/installer/util:strings", + "//chrome_elf", + "//chrome_elf:constants", + "//chrome_elf:dll_hash", "//google_update", "//third_party/iaccessible2", "//third_party/isimpledom", "//third_party/wtl", #"chrome_process_finder", TODO(GYP) - #"../chrome_elf/chrome_elf.gyp:chrome_elf", TODO(GYP) - #"../chrome_elf/chrome_elf.gyp:chrome_elf_constants", TODO(GYP) - #"../chrome_elf/chrome_elf.gyp:dll_hash", TODO(GYP) "//ui/metro_viewer", "//win8:metro_viewer", ] @@ -787,9 +787,8 @@ deps = [ ":about_credits", ":chrome_internal_resources_gen", - "//chrome/browser/ui/webui/omnibox:mojo_bindings", - "//mojo/environment:chromium", ] + data_deps = [ "//chrome/browser/ui/webui/omnibox:mojo_bindings" ] } # GYP version: chrome/chrome_resource.gyp:about_credits @@ -890,6 +889,8 @@ "search_engines/template_url_service_factory_test_util.h", "search_engines/template_url_service_test_util.cc", "search_engines/template_url_service_test_util.h", + "sessions/session_restore_test_helper.cc", + "sessions/session_restore_test_helper.h", "sessions/session_service_test_helper.cc", "sessions/session_service_test_helper.h", "signin/fake_account_reconcilor.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 270e77c5..decc6fe 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -188,6 +188,16 @@ }; #endif +const Experiment::Choice kMarkNonSecureAsChoices[] = { + { IDS_GENERIC_EXPERIMENT_CHOICE_DEFAULT, "", "" }, + { IDS_MARK_NON_SECURE_AS_NEUTRAL, + switches::kMarkNonSecureAs, switches::kMarkNonSecureAsNeutral}, + { IDS_MARK_NON_SECURE_AS_NON_SECURE, + switches::kMarkNonSecureAs, switches::kMarkNonSecureAsNonSecure}, + { IDS_MARK_NON_SECURE_AS_DUBIOUS, + switches::kMarkNonSecureAs, switches::kMarkNonSecureAsDubious} +}; + const Experiment::Choice kMaxTilesForInterestAreaChoices[] = { { IDS_GENERIC_EXPERIMENT_CHOICE_DEFAULT, "", "" }, { IDS_FLAGS_MAX_TILES_FOR_INTEREST_AREA_SHORT, @@ -698,11 +708,11 @@ SINGLE_VALUE_TYPE(switches::kDisableMediaSource) }, { - "enable-encrypted-media", - IDS_FLAGS_ENABLE_ENCRYPTED_MEDIA_NAME, - IDS_FLAGS_ENABLE_ENCRYPTED_MEDIA_DESCRIPTION, + "disable-encrypted-media", + IDS_FLAGS_DISABLE_ENCRYPTED_MEDIA_NAME, + IDS_FLAGS_DISABLE_ENCRYPTED_MEDIA_DESCRIPTION, kOsAll, - SINGLE_VALUE_TYPE(switches::kEnableEncryptedMedia) + SINGLE_VALUE_TYPE(switches::kDisableEncryptedMedia) }, { "disable-prefixed-encrypted-media", @@ -1155,14 +1165,6 @@ }, #endif { - "impl-side-painting", - IDS_FLAGS_IMPL_SIDE_PAINTING_NAME, - IDS_FLAGS_IMPL_SIDE_PAINTING_DESCRIPTION, - kOsAll, - ENABLE_DISABLE_VALUE_TYPE(switches::kEnableImplSidePainting, - switches::kDisableImplSidePainting) - }, - { "lcd-text-aa", IDS_FLAGS_LCD_TEXT_NAME, IDS_FLAGS_LCD_TEXT_DESCRIPTION, @@ -1349,13 +1351,6 @@ switches::kDisableDeviceDiscoveryNotifications) }, { - "enable-cloud-devices", - IDS_FLAGS_ENABLE_CLOUD_DEVICES_NAME, - IDS_FLAGS_ENABLE_CLOUD_DEVICES_DESCRIPTION, - kOsDesktop, - SINGLE_VALUE_TYPE(switches::kEnableCloudDevices) - }, - { "enable-print-preview-register-promos", IDS_FLAGS_ENABLE_PRINT_PREVIEW_REGISTER_PROMOS_NAME, IDS_FLAGS_ENABLE_PRINT_PREVIEW_REGISTER_PROMOS_DESCRIPTION, @@ -1484,13 +1479,6 @@ }, #endif { - "disable-app-list-app-info", - IDS_FLAGS_DISABLE_APP_INFO_IN_APP_LIST, - IDS_FLAGS_DISABLE_APP_INFO_IN_APP_LIST_DESCRIPTION, - kOsLinux | kOsWin | kOsCrOS, - SINGLE_VALUE_TYPE(app_list::switches::kDisableAppInfo) - }, - { "disable-drive-apps-in-app-list", IDS_FLAGS_DISABLE_DRIVE_APPS_IN_APP_LIST_NAME, IDS_FLAGS_DISABLE_DRIVE_APPS_IN_APP_LIST_DESCRIPTION, @@ -2155,6 +2143,14 @@ SINGLE_VALUE_TYPE(switches::kEnableDelayAgnosticAec) }, + { + "mark-non-secure-as", // FLAGS:RECORD_UMA + IDS_MARK_NON_SECURE_AS_NAME, + IDS_MARK_NON_SECURE_AS_DESCRIPTION, + kOsAll, + MULTI_VALUE_TYPE(kMarkNonSecureAsChoices) + }, + // NOTE: Adding new command-line switches requires adding corresponding // entries to enum "LoginCustomFlags" in histograms.xml. See note in // histograms.xml and don't forget to run AboutFlagsHistogramTest unit test.
diff --git a/chrome/browser/android/omnibox/autocomplete_controller_android.cc b/chrome/browser/android/omnibox/autocomplete_controller_android.cc index 020ce67..0b5d22d 100644 --- a/chrome/browser/android/omnibox/autocomplete_controller_android.cc +++ b/chrome/browser/android/omnibox/autocomplete_controller_android.cc
@@ -224,7 +224,6 @@ true, selected_index, false, - false, /* don't know */ SessionTabHelper::IdForTab(web_contents), current_page_classification, base::TimeDelta::FromMilliseconds(elapsed_time_since_first_modified),
diff --git a/chrome/browser/android/preferences/pref_service_bridge.cc b/chrome/browser/android/preferences/pref_service_bridge.cc index aa37726..c37b4e0b 100644 --- a/chrome/browser/android/preferences/pref_service_bridge.cc +++ b/chrome/browser/android/preferences/pref_service_bridge.cc
@@ -59,8 +59,9 @@ return ProfileManager::GetActiveUserProfile()->GetOriginalProfile(); } -bool GetBooleanForContentSetting(HostContentSettingsMap* content_settings, - ContentSettingsType type) { +bool GetBooleanForContentSetting(ContentSettingsType type) { + HostContentSettingsMap* content_settings = + GetOriginalProfile()->GetHostContentSettingsMap(); switch (content_settings->GetDefaultContentSetting(type, NULL)) { case CONTENT_SETTING_BLOCK: return false; @@ -93,18 +94,20 @@ } } -bool IsContentSettingManaged(HostContentSettingsMap* content_settings, - ContentSettingsType content_settings_type) { +bool IsContentSettingManaged(ContentSettingsType content_settings_type) { std::string source; + HostContentSettingsMap* content_settings = + GetOriginalProfile()->GetHostContentSettingsMap(); content_settings->GetDefaultContentSetting(content_settings_type, &source); HostContentSettingsMap::ProviderType provider = content_settings->GetProviderTypeFromSource(source); return provider == HostContentSettingsMap::POLICY_PROVIDER; } -bool IsContentSettingUserModifiable(HostContentSettingsMap* content_settings, - ContentSettingsType content_settings_type) { +bool IsContentSettingUserModifiable(ContentSettingsType content_settings_type) { std::string source; + HostContentSettingsMap* content_settings = + GetOriginalProfile()->GetHostContentSettingsMap(); content_settings->GetDefaultContentSetting(content_settings_type, &source); HostContentSettingsMap::ProviderType provider = content_settings->GetProviderTypeFromSource(source); @@ -132,57 +135,6 @@ return GetOriginalProfile()->GetPrefs(); } -static void EnsureConsistentGeolocationPreferences(Profile* profile) { - // On Android, we use the kGeolocationEnabled flag to control geolocation on a - // global basis, rather than the default geolocation host content setting, - // which is only used if no previously stored more specific host exception - // cannot be found. - // - // On Android, there is currently no UI to change this default setting, so it - // needs to default to ASK. Additionally, for users that have previously set - // the default to BLOCK, we set the preference to disable geolocation - // globally. - - ContentSetting defaultSetting = profile->GetHostContentSettingsMap()-> - GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_GEOLOCATION, NULL); - - if (defaultSetting == CONTENT_SETTING_ASK) - return; - - profile->GetHostContentSettingsMap()->SetDefaultContentSetting( - CONTENT_SETTINGS_TYPE_GEOLOCATION, CONTENT_SETTING_ASK); - - if (defaultSetting == CONTENT_SETTING_BLOCK) { - profile->GetPrefs()->SetBoolean(prefs::kGeolocationEnabled, false); - } -} - -static void EnsureConsistentProtectedMediaIdentifierPreferences( - Profile* profile) { - // We use the kProtectedMediaIdentifierEnabled flag to control protected media - // identifier on a global basis. - // - // On Android, there is currently no UI to change this default setting, so it - // needs to default to ASK. Additionally, for users that have previously set - // the default to BLOCK, we set the preference to disable protected media - // identifier globally. - ContentSetting defaultSetting = - profile->GetHostContentSettingsMap()-> - GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER, - NULL); - - if (defaultSetting == CONTENT_SETTING_ASK) - return; - - profile->GetHostContentSettingsMap()->SetDefaultContentSetting( - CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER, CONTENT_SETTING_ASK); - - if (defaultSetting == CONTENT_SETTING_BLOCK) { - profile->GetPrefs()->SetBoolean(prefs::kProtectedMediaIdentifierEnabled, - false); - } -} - } // namespace // ---------------------------------------------------------------------------- @@ -190,15 +142,11 @@ // ---------------------------------------------------------------------------- static jboolean GetAcceptCookiesEnabled(JNIEnv* env, jobject obj) { - return GetBooleanForContentSetting( - GetOriginalProfile()->GetHostContentSettingsMap(), - CONTENT_SETTINGS_TYPE_COOKIES); + return GetBooleanForContentSetting(CONTENT_SETTINGS_TYPE_COOKIES); } static jboolean GetAcceptCookiesManaged(JNIEnv* env, jobject obj) { - return IsContentSettingManaged( - GetOriginalProfile()->GetHostContentSettingsMap(), - CONTENT_SETTINGS_TYPE_COOKIES); + return IsContentSettingManaged(CONTENT_SETTINGS_TYPE_COOKIES); } static jboolean GetBlockThirdPartyCookiesEnabled(JNIEnv* env, jobject obj) { @@ -261,37 +209,22 @@ } static jboolean GetProtectedMediaIdentifierEnabled(JNIEnv* env, jobject obj) { - Profile* profile = GetOriginalProfile(); - EnsureConsistentProtectedMediaIdentifierPreferences(profile); - HostContentSettingsMap* content_settings = - profile->GetHostContentSettingsMap(); return GetBooleanForContentSetting( - content_settings, CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER) && GetPrefService()->GetBoolean(prefs::kProtectedMediaIdentifierEnabled); } static jboolean GetPushNotificationsEnabled(JNIEnv* env, jobject obj) { - HostContentSettingsMap* content_settings = - GetOriginalProfile()->GetHostContentSettingsMap(); - return GetBooleanForContentSetting(content_settings, - CONTENT_SETTINGS_TYPE_NOTIFICATIONS); + return GetBooleanForContentSetting(CONTENT_SETTINGS_TYPE_NOTIFICATIONS); } static jboolean GetAllowLocationEnabled(JNIEnv* env, jobject obj) { - Profile* profile = GetOriginalProfile(); - EnsureConsistentGeolocationPreferences(profile); - HostContentSettingsMap* content_settings = - profile->GetHostContentSettingsMap(); - return GetBooleanForContentSetting(content_settings, - CONTENT_SETTINGS_TYPE_GEOLOCATION) && + return GetBooleanForContentSetting(CONTENT_SETTINGS_TYPE_GEOLOCATION) && GetPrefService()->GetBoolean(prefs::kGeolocationEnabled); } static jboolean GetAllowLocationUserModifiable(JNIEnv* env, jobject obj) { - return IsContentSettingUserModifiable( - GetOriginalProfile()->GetHostContentSettingsMap(), - CONTENT_SETTINGS_TYPE_GEOLOCATION) && + return IsContentSettingUserModifiable(CONTENT_SETTINGS_TYPE_GEOLOCATION) && GetPrefService()->IsUserModifiablePreference( prefs::kGeolocationEnabled); } @@ -476,10 +409,7 @@ } static jboolean GetJavaScriptManaged(JNIEnv* env, jobject obj) { - HostContentSettingsMap* content_settings = - GetOriginalProfile()->GetHostContentSettingsMap(); - return IsContentSettingManaged( - content_settings, CONTENT_SETTINGS_TYPE_JAVASCRIPT); + return IsContentSettingManaged(CONTENT_SETTINGS_TYPE_JAVASCRIPT); } static void SetJavaScriptEnabled(JNIEnv* env, jobject obj, jboolean enabled) { @@ -490,11 +420,8 @@ // The user pref for Javascript is stored in kWebKitJavascriptEnabled for // historical reasons, but the content setting is where a possibly managed // value will be enforced. - HostContentSettingsMap* content_settings = - GetOriginalProfile()->GetHostContentSettingsMap(); - - jboolean javascript_enabled = GetBooleanForContentSetting( - content_settings, CONTENT_SETTINGS_TYPE_JAVASCRIPT); + jboolean javascript_enabled = + GetBooleanForContentSetting(CONTENT_SETTINGS_TYPE_JAVASCRIPT); if (!GetJavaScriptManaged(env, obj)) { javascript_enabled &= GetPrefService()->GetBoolean( prefs::kWebKitJavascriptEnabled); @@ -510,17 +437,11 @@ } static jboolean GetAllowPopupsEnabled(JNIEnv* env, jobject obj) { - HostContentSettingsMap* content_settings = - GetOriginalProfile()->GetHostContentSettingsMap(); - return GetBooleanForContentSetting(content_settings, - CONTENT_SETTINGS_TYPE_POPUPS); + return GetBooleanForContentSetting(CONTENT_SETTINGS_TYPE_POPUPS); } static jboolean GetAllowPopupsManaged(JNIEnv* env, jobject obj) { - HostContentSettingsMap* content_settings = - GetOriginalProfile()->GetHostContentSettingsMap(); - return IsContentSettingManaged(content_settings, - CONTENT_SETTINGS_TYPE_POPUPS); + return IsContentSettingManaged(CONTENT_SETTINGS_TYPE_POPUPS); } static void SetAllowPopupsEnabled(JNIEnv* env, jobject obj, jboolean allow) { @@ -532,20 +453,15 @@ } static jboolean GetCameraMicEnabled(JNIEnv* env, jobject obj) { - HostContentSettingsMap* content_settings = - GetOriginalProfile()->GetHostContentSettingsMap(); PrefService* prefs = GetPrefService(); - return GetBooleanForContentSetting(content_settings, - CONTENT_SETTINGS_TYPE_MEDIASTREAM) && + return GetBooleanForContentSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM) && prefs->GetBoolean(prefs::kAudioCaptureAllowed) && prefs->GetBoolean(prefs::kVideoCaptureAllowed); } static jboolean GetCameraMicUserModifiable(JNIEnv* env, jobject obj) { PrefService* prefs = GetPrefService(); - return IsContentSettingUserModifiable( - GetOriginalProfile()->GetHostContentSettingsMap(), - CONTENT_SETTINGS_TYPE_MEDIASTREAM) && + return IsContentSettingUserModifiable(CONTENT_SETTINGS_TYPE_MEDIASTREAM) && prefs->IsUserModifiablePreference(prefs::kAudioCaptureAllowed) && prefs->IsUserModifiablePreference(prefs::kVideoCaptureAllowed); }
diff --git a/chrome/browser/android/provider/chrome_browser_provider.cc b/chrome/browser/android/provider/chrome_browser_provider.cc index 3a71063..d1e9c1a 100644 --- a/chrome/browser/android/provider/chrome_browser_provider.cc +++ b/chrome/browser/android/provider/chrome_browser_provider.cc
@@ -1637,6 +1637,10 @@ Java_ChromeBrowserProvider_onSearchTermChanged(env, obj.obj()); } +void ChromeBrowserProvider::OnKeywordSearchTermDeleted( + HistoryService* history_service, + history::URLID url_id) {} + void ChromeBrowserProvider::Observe( int type, const content::NotificationSource& source,
diff --git a/chrome/browser/android/provider/chrome_browser_provider.h b/chrome/browser/android/provider/chrome_browser_provider.h index 15b6613..56b4ffdc 100644 --- a/chrome/browser/android/provider/chrome_browser_provider.h +++ b/chrome/browser/android/provider/chrome_browser_provider.h
@@ -197,6 +197,8 @@ const history::URLRow& row, history::KeywordID keyword_id, const base::string16& term) override; + void OnKeywordSearchTermDeleted(HistoryService* history_service, + history::URLID url_id) override; // Override content::NotificationObserver. virtual void Observe(int type,
diff --git a/chrome/browser/android/tab_android.cc b/chrome/browser/android/tab_android.cc index e7ce1c8..840b3f8 100644 --- a/chrome/browser/android/tab_android.cc +++ b/chrome/browser/android/tab_android.cc
@@ -499,7 +499,8 @@ jint page_transition, jstring j_referrer_url, jint referrer_policy, - jboolean is_renderer_initiated) { + jboolean is_renderer_initiated, + jlong intent_received_timestamp) { if (!web_contents()) return PAGE_LOAD_FAILED; @@ -581,6 +582,7 @@ return DEFAULT_PAGE_LOAD; } load_params.is_renderer_initiated = is_renderer_initiated; + load_params.intent_received_timestamp = intent_received_timestamp; web_contents()->GetController().LoadURLWithParams(load_params); } return DEFAULT_PAGE_LOAD;
diff --git a/chrome/browser/android/tab_android.h b/chrome/browser/android/tab_android.h index d411470..57c019b 100644 --- a/chrome/browser/android/tab_android.h +++ b/chrome/browser/android/tab_android.h
@@ -153,7 +153,8 @@ jint page_transition, jstring j_referrer_url, jint referrer_policy, - jboolean is_renderer_initiated); + jboolean is_renderer_initiated, + jlong intent_received_timestamp); void SetActiveNavigationEntryTitleForUrl(JNIEnv* env, jobject obj, jstring jurl,
diff --git a/chrome/browser/app_controller_mac.mm b/chrome/browser/app_controller_mac.mm index 0870911..41043f7f 100644 --- a/chrome/browser/app_controller_mac.mm +++ b/chrome/browser/app_controller_mac.mm
@@ -1136,7 +1136,8 @@ break; case IDC_SHOW_SYNC_SETUP: if (Browser* browser = ActivateBrowser(lastProfile)) { - chrome::ShowBrowserSignin(browser, signin_metrics::SOURCE_MENU); + chrome::ShowBrowserSigninOrSettings(browser, + signin_metrics::SOURCE_MENU); } else { chrome::OpenSyncSetupWindow(lastProfile, signin_metrics::SOURCE_MENU); }
diff --git a/chrome/browser/app_controller_mac_browsertest.mm b/chrome/browser/app_controller_mac_browsertest.mm index d72b6f91..52fa358b 100644 --- a/chrome/browser/app_controller_mac_browsertest.mm +++ b/chrome/browser/app_controller_mac_browsertest.mm
@@ -202,12 +202,12 @@ quit_closure.Run(); } -void CreateAndWaitForGuestProfile() { +void CreateAndWaitForSystemProfile() { ProfileManager::CreateCallback create_callback = base::Bind(&CreateProfileCallback, base::MessageLoop::current()->QuitClosure()); g_browser_process->profile_manager()->CreateProfileAsync( - ProfileManager::GetGuestProfilePath(), + ProfileManager::GetSystemProfilePath(), create_callback, base::string16(), base::string16(), @@ -245,10 +245,10 @@ // Test that for a locked last profile, a reopen event opens the User Manager. IN_PROC_BROWSER_TEST_F(AppControllerNewProfileManagementBrowserTest, LockedProfileReopenWithNoWindows) { - // The User Manager uses the guest profile as its underlying profile. To + // The User Manager uses the system profile as its underlying profile. To // minimize flakiness due to the scheduling/descheduling of tasks on the // different threads, pre-initialize the guest profile before it is needed. - CreateAndWaitForGuestProfile(); + CreateAndWaitForSystemProfile(); base::scoped_nsobject<AppController> ac([[AppController alloc] init]); // Lock the active profile. @@ -272,9 +272,9 @@ // Test that for a guest last profile, a reopen event opens the User Manager. IN_PROC_BROWSER_TEST_F(AppControllerNewProfileManagementBrowserTest, GuestProfileReopenWithNoWindows) { - // Create the guest profile, and set it as the last used profile so the + // Create the system profile. Set the guest as the last used profile so the // app controller can use it on init. - CreateAndWaitForGuestProfile(); + CreateAndWaitForSystemProfile(); PrefService* local_state = g_browser_process->local_state(); local_state->SetString(prefs::kProfileLastUsed, chrome::kGuestProfileDir); @@ -301,7 +301,7 @@ // Create the guest profile, and set it as the last used profile so the // app controller can use it on init. - CreateAndWaitForGuestProfile(); + CreateAndWaitForSystemProfile(); PrefService* local_state = g_browser_process->local_state(); local_state->SetString(prefs::kProfileLastUsed, chrome::kGuestProfileDir);
diff --git a/chrome/browser/apps/app_shim/app_shim_interactive_uitest_mac.mm b/chrome/browser/apps/app_shim/app_shim_interactive_uitest_mac.mm index 5ea5e69..59c61d6b 100644 --- a/chrome/browser/apps/app_shim/app_shim_interactive_uitest_mac.mm +++ b/chrome/browser/apps/app_shim/app_shim_interactive_uitest_mac.mm
@@ -34,7 +34,6 @@ #include "content/public/test/test_utils.h" #include "extensions/browser/app_window/native_app_window.h" #include "extensions/browser/extension_prefs.h" -#include "extensions/browser/extension_registry.h" #include "extensions/test/extension_test_message_listener.h" #import "ui/events/test/cocoa_test_event_utils.h" @@ -375,9 +374,8 @@ NSString* bundle_id = GetBundleID(shim_path); // Explicitly set the launch type to open in a new window. - extensions::SetLaunchType( - extensions::ExtensionSystem::Get(profile())->extension_service(), - app->id(), extensions::LAUNCH_TYPE_WINDOW); + extensions::SetLaunchType(profile(), app->id(), + extensions::LAUNCH_TYPE_WINDOW); // Case 1: Launch the hosted app, it should start the shim. {
diff --git a/chrome/browser/apps/drive/drive_service_bridge.cc b/chrome/browser/apps/drive/drive_service_bridge.cc index b9d90c9..bb56d034 100644 --- a/chrome/browser/apps/drive/drive_service_bridge.cc +++ b/chrome/browser/apps/drive/drive_service_bridge.cc
@@ -83,7 +83,6 @@ drive_task_runner.get(), GURL(google_apis::DriveApiUrlGenerator::kBaseUrlForProduction), GURL(google_apis::DriveApiUrlGenerator::kBaseDownloadUrlForProduction), - GURL(google_apis::GDataWapiUrlGenerator::kBaseUrlForProduction), std::string() /* custom_user_agent */)); SigninManagerBase* signin_manager = SigninManagerFactory::GetForProfile(profile_);
diff --git a/chrome/browser/apps/guest_view/web_view_browsertest.cc b/chrome/browser/apps/guest_view/web_view_browsertest.cc index 79de391..b875bcc 100644 --- a/chrome/browser/apps/guest_view/web_view_browsertest.cc +++ b/chrome/browser/apps/guest_view/web_view_browsertest.cc
@@ -844,7 +844,7 @@ } // Test for http://crbug.com/419611. -IN_PROC_BROWSER_TEST_F(WebViewTest, DISABLED_DisplayNoneSetSrc) { +IN_PROC_BROWSER_TEST_F(WebViewTest, DisplayNoneSetSrc) { LoadAndLaunchPlatformApp("web_view/display_none_set_src", "WebViewTest.LAUNCHED"); // Navigate the guest while it's in "display: none" state. @@ -1089,7 +1089,7 @@ // TODO(fsamuel): Enable this test once <webview> can run in a detached state. IN_PROC_BROWSER_TEST_F(WebViewTest, - DISABLED_Shim_TestContentLoadEventWithDisplayNone) { + Shim_TestContentLoadEventWithDisplayNone) { TestHelper("testContentLoadEventWithDisplayNone", "web_view/shim", NO_TEST_SERVER);
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc index 2d32b62..d8b45ea7 100644 --- a/chrome/browser/browser_process_impl.cc +++ b/chrome/browser/browser_process_impl.cc
@@ -861,13 +861,14 @@ if (!component_updater_.get()) { if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) return NULL; - component_updater::Configurator* configurator = + update_client::Configurator* configurator = component_updater::MakeChromeComponentUpdaterConfigurator( base::CommandLine::ForCurrentProcess(), io_thread()->system_url_request_context_getter()); // Creating the component updater does not do anything, components // need to be registered and Start() needs to be called. - component_updater_.reset(ComponentUpdateServiceFactory(configurator)); + component_updater_.reset( + component_updater::ComponentUpdateServiceFactory(configurator)); } return component_updater_.get(); }
diff --git a/chrome/browser/browsing_data/browsing_data_remover.cc b/chrome/browser/browsing_data/browsing_data_remover.cc index 7987a92b..189586b 100644 --- a/chrome/browser/browsing_data/browsing_data_remover.cc +++ b/chrome/browser/browsing_data/browsing_data_remover.cc
@@ -101,6 +101,24 @@ using content::BrowserThread; using content::DOMStorageContext; +namespace { + +using CallbackList = + base::CallbackList<void(const BrowsingDataRemover::NotificationDetails&)>; + +// Contains all registered callbacks for browsing data removed notifications. +CallbackList* g_on_browsing_data_removed_callbacks = nullptr; + +// Accessor for |*g_on_browsing_data_removed_callbacks|. Creates a new object +// the first time so that it always returns a valid object. +CallbackList* GetOnBrowsingDataRemovedCallbacks() { + if (!g_on_browsing_data_removed_callbacks) + g_on_browsing_data_removed_callbacks = new CallbackList(); + return g_on_browsing_data_removed_callbacks; +} + +} // namespace + bool BrowsingDataRemover::is_removing_ = false; BrowsingDataRemover::CompletionInhibitor* @@ -808,13 +826,11 @@ void BrowsingDataRemover::NotifyAndDelete() { set_removing(false); - // Send global notification, then notify any explicit observers. + // Notify observers. BrowsingDataRemover::NotificationDetails details(delete_begin_, remove_mask_, origin_set_mask_); - content::NotificationService::current()->Notify( - chrome::NOTIFICATION_BROWSING_DATA_REMOVED, - content::Source<Profile>(profile_), - content::Details<BrowsingDataRemover::NotificationDetails>(&details)); + + GetOnBrowsingDataRemovedCallbacks()->Notify(details); FOR_EACH_OBSERVER(Observer, observer_list_, OnBrowsingDataRemoverDone()); @@ -1199,3 +1215,10 @@ waiting_for_clear_domain_reliability_monitor_ = false; NotifyAndDeleteIfDone(); } + +// static +BrowsingDataRemover::CallbackSubscription + BrowsingDataRemover::RegisterOnBrowsingDataRemovedCallback( + const BrowsingDataRemover::Callback& callback) { + return GetOnBrowsingDataRemovedCallbacks()->Add(callback); +}
diff --git a/chrome/browser/browsing_data/browsing_data_remover.h b/chrome/browser/browsing_data/browsing_data_remover.h index 133a89a..174458d 100644 --- a/chrome/browser/browsing_data/browsing_data_remover.h +++ b/chrome/browser/browsing_data/browsing_data_remover.h
@@ -152,6 +152,10 @@ virtual ~Observer() {} }; + using Callback = base::Callback<void(const NotificationDetails&)>; + using CallbackSubscription = scoped_ptr< + base::CallbackList<void(const NotificationDetails&)>::Subscription>; + // The completion inhibitor can artificially delay completion of the browsing // data removal process. It is used during testing to simulate scenarios in // which the deletion stalls or takes a very long time. @@ -200,6 +204,12 @@ completion_inhibitor_ = inhibitor; } + // Add a callback to the list of callbacks to be called during a browsing data + // removal event. Returns a subscription object that can be used to + // un-register the callback. + static CallbackSubscription RegisterOnBrowsingDataRemovedCallback( + const Callback& callback); + // Removes the specified items related to browsing for all origins that match // the provided |origin_set_mask| (see BrowsingDataHelper::OriginSetMask). void Remove(int remove_mask, int origin_set_mask);
diff --git a/chrome/browser/browsing_data/browsing_data_remover_unittest.cc b/chrome/browser/browsing_data/browsing_data_remover_unittest.cc index afdc2d3e..7d1e71a 100644 --- a/chrome/browser/browsing_data/browsing_data_remover_unittest.cc +++ b/chrome/browser/browsing_data/browsing_data_remover_unittest.cc
@@ -20,7 +20,6 @@ #include "chrome/browser/autofill/personal_data_manager_factory.h" #include "chrome/browser/browsing_data/browsing_data_helper.h" #include "chrome/browser/browsing_data/browsing_data_remover_test_util.h" -#include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/domain_reliability/service_factory.h" #include "chrome/browser/history/history_service.h" #include "chrome/browser/history/history_service_factory.h" @@ -39,7 +38,6 @@ #include "content/public/browser/cookie_store_factory.h" #include "content/public/browser/dom_storage_context.h" #include "content/public/browser/local_storage_usage_info.h" -#include "content/public/browser/notification_service.h" #include "content/public/browser/storage_partition.h" #include "content/public/test/test_browser_thread.h" #include "content/public/test/test_browser_thread_bundle.h" @@ -703,13 +701,13 @@ // Test Class ---------------------------------------------------------------- -class BrowsingDataRemoverTest : public testing::Test, - public content::NotificationObserver { +class BrowsingDataRemoverTest : public testing::Test { public: - BrowsingDataRemoverTest() - : profile_(new TestingProfile()) { - registrar_.Add(this, chrome::NOTIFICATION_BROWSING_DATA_REMOVED, - content::Source<Profile>(profile_.get())); + BrowsingDataRemoverTest() : profile_(new TestingProfile()) { + callback_subscription_ = + BrowsingDataRemover::RegisterOnBrowsingDataRemovedCallback( + base::Bind(&BrowsingDataRemoverTest::NotifyWithDetails, + base::Unretained(this))); } ~BrowsingDataRemoverTest() override {} @@ -794,19 +792,15 @@ return storage_partition_removal_data_; } - // content::NotificationObserver implementation. - void Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) override { - DCHECK_EQ(type, chrome::NOTIFICATION_BROWSING_DATA_REMOVED); - + // Callback for browsing data removal events. + void NotifyWithDetails( + const BrowsingDataRemover::NotificationDetails& details) { // We're not taking ownership of the details object, but storing a copy of // it locally. - called_with_details_.reset(new BrowsingDataRemover::NotificationDetails( - *content::Details<BrowsingDataRemover::NotificationDetails>( - details).ptr())); + called_with_details_.reset( + new BrowsingDataRemover::NotificationDetails(details)); - registrar_.RemoveAll(); + callback_subscription_.reset(); } MockExtensionSpecialStoragePolicy* CreateMockPolicy() { @@ -841,8 +835,6 @@ scoped_ptr<BrowsingDataRemover::NotificationDetails> called_with_details_; private: - content::NotificationRegistrar registrar_; - content::TestBrowserThreadBundle thread_bundle_; scoped_ptr<TestingProfile> profile_; @@ -852,6 +844,8 @@ scoped_refptr<MockExtensionSpecialStoragePolicy> mock_policy_; #endif + BrowsingDataRemover::CallbackSubscription callback_subscription_; + DISALLOW_COPY_AND_ASSIGN(BrowsingDataRemoverTest); };
diff --git a/chrome/browser/captive_portal/captive_portal_browsertest.cc b/chrome/browser/captive_portal/captive_portal_browsertest.cc index 1560e3a..7fd8389 100644 --- a/chrome/browser/captive_portal/captive_portal_browsertest.cc +++ b/chrome/browser/captive_portal/captive_portal_browsertest.cc
@@ -120,30 +120,6 @@ // captive portal. const char* const kInternetConnectedTitle = "Title Of Awesomeness"; -// Wait until all resources have loaded in an interstitial page. -bool WaitForInterstitialReady(content::InterstitialPage* interstitial) { - content::RenderFrameHost* rfh = interstitial->GetMainFrame(); - if (!rfh) - return false; - bool load_complete = false; - EXPECT_TRUE( - content::ExecuteScriptAndExtractBool( - rfh, - "(function() {" - " var done = false;" - " function checkState() {" - " if (!done && document.readyState == 'complete') {" - " done = true;" - " window.domAutomationController.send(true);" - " }" - " }" - " checkState();" - " document.addEventListener('readystatechange', checkState);" - "})();", - &load_complete)); - return load_complete; -} - // A URL request job that hangs until FailJobs() is called. Started jobs // are stored in a static class variable containing a linked list so that // FailJobs() can locate them. @@ -1982,10 +1958,9 @@ tab_strip_model->ActivateTabAt(cert_error_tab_index, false); // Wait for the interstitial to load all the JavaScript code. Otherwise, // trying to click on a button will fail. - EXPECT_TRUE(WaitForInterstitialReady( - broken_tab_contents->GetInterstitialPage())); content::RenderFrameHost* rfh = broken_tab_contents->GetInterstitialPage()->GetMainFrame(); + EXPECT_TRUE(WaitForRenderFrameReady(rfh)); const char kClickConnectButtonJS[] = "document.getElementById('primary-button').click();"; EXPECT_TRUE(
diff --git a/chrome/browser/captive_portal/captive_portal_service.cc b/chrome/browser/captive_portal/captive_portal_service.cc index dd3bff4d..6098d80e 100644 --- a/chrome/browser/captive_portal/captive_portal_service.cc +++ b/chrome/browser/captive_portal/captive_portal_service.cc
@@ -241,7 +241,7 @@ // Count this as a success, so the backoff entry won't apply exponential // backoff, but will apply the standard delay. backoff_entry_->InformOfRequest(true); - OnResult(captive_portal::RESULT_INTERNET_CONNECTED); + OnResult(captive_portal::RESULT_INTERNET_CONNECTED, GURL()); return; } @@ -307,7 +307,7 @@ last_check_time_ = now; - OnResult(result); + OnResult(result, results.landing_url); } void CaptivePortalService::Shutdown() { @@ -320,13 +320,15 @@ } } -void CaptivePortalService::OnResult(CaptivePortalResult result) { +void CaptivePortalService::OnResult(CaptivePortalResult result, + const GURL& landing_url) { DCHECK_EQ(STATE_CHECKING_FOR_PORTAL, state_); state_ = STATE_IDLE; Results results; results.previous_result = last_detection_result_; results.result = result; + results.landing_url = landing_url; last_detection_result_ = result; content::NotificationService::current()->Notify(
diff --git a/chrome/browser/captive_portal/captive_portal_service.h b/chrome/browser/captive_portal/captive_portal_service.h index 2e24e439..c48ca5d37 100644 --- a/chrome/browser/captive_portal/captive_portal_service.h +++ b/chrome/browser/captive_portal/captive_portal_service.h
@@ -42,6 +42,9 @@ captive_portal::CaptivePortalResult previous_result; // The result of the most recent captive portal check. captive_portal::CaptivePortalResult result; + // Landing url of the captive portal check ping. If behind a captive portal, + // this points to the login page. + GURL landing_url; }; explicit CaptivePortalService(Profile* profile); @@ -120,7 +123,8 @@ // Called when a captive portal check completes. Passes the result to all // observers. - void OnResult(captive_portal::CaptivePortalResult result); + void OnResult(captive_portal::CaptivePortalResult result, + const GURL& landing_url); // Updates BackoffEntry::Policy and creates a new BackoffEntry, which // resets the count used for throttling.
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index a45399ec..f183f91 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -1962,7 +1962,12 @@ context = GeolocationPermissionContextFactory::GetForProfile(profile); break; case content::PERMISSION_PROTECTED_MEDIA: +#if defined(OS_ANDROID) + context = ProtectedMediaIdentifierPermissionContextFactory::GetForProfile( + profile); +#else NOTIMPLEMENTED(); +#endif break; case content::PERMISSION_PUSH_MESSAGING: context = gcm::PushMessagingPermissionContextFactory::GetForProfile(
diff --git a/chrome/browser/chrome_content_browser_client_unittest.cc b/chrome/browser/chrome_content_browser_client_unittest.cc index 32ed674..9ea8f8c 100644 --- a/chrome/browser/chrome_content_browser_client_unittest.cc +++ b/chrome/browser/chrome_content_browser_client_unittest.cc
@@ -11,6 +11,7 @@ #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/test/base/browser_with_test_window_test.h" #include "chrome/test/base/ui_test_utils.h" +#include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/search_engines/template_url_service.h" #include "components/variations/entropy_provider.h" #include "content/public/browser/navigation_controller.h" @@ -137,3 +138,65 @@ } // namespace content #endif // !defined(OS_IOS) && !defined(OS_ANDROID) + +namespace chrome { + +// For testing permissions related functionality. +class PermissionBrowserClientTest : public testing::Test { + public: + PermissionBrowserClientTest() : url_("https://www.google.com") {} + + void CheckPermissionStatus(content::PermissionType type, + content::PermissionStatus expected) { + EXPECT_EQ(expected, client_.GetPermissionStatus(type, &profile_, + url_.GetOrigin(), + url_.GetOrigin())); + } + + void SetPermission(ContentSettingsType type, ContentSetting value) { + profile_.GetHostContentSettingsMap()->SetContentSetting( + ContentSettingsPattern::FromURLNoWildcard(url_), + ContentSettingsPattern::FromURLNoWildcard(url_), + type, std::string(), value); + } + + private: + content::TestBrowserThreadBundle thread_bundle_; + ChromeContentBrowserClient client_; + TestingProfile profile_; + GURL url_; +}; + +TEST_F(PermissionBrowserClientTest, GetPermissionStatusDefault) { + using namespace content; + CheckPermissionStatus(PERMISSION_MIDI_SYSEX, PERMISSION_STATUS_ASK); + CheckPermissionStatus(PERMISSION_PUSH_MESSAGING, PERMISSION_STATUS_ASK); + CheckPermissionStatus(PERMISSION_NOTIFICATIONS, PERMISSION_STATUS_ASK); + CheckPermissionStatus(PERMISSION_GEOLOCATION, PERMISSION_STATUS_ASK); +#if defined(OS_ANDROID) + CheckPermissionStatus(PERMISSION_PROTECTED_MEDIA, PERMISSION_STATUS_ASK); +#endif +} + +TEST_F(PermissionBrowserClientTest, GetPermissionStatusAfterSet) { + using namespace content; + SetPermission(CONTENT_SETTINGS_TYPE_GEOLOCATION, CONTENT_SETTING_ALLOW); + CheckPermissionStatus(PERMISSION_GEOLOCATION, PERMISSION_STATUS_GRANTED); + + SetPermission(CONTENT_SETTINGS_TYPE_NOTIFICATIONS, CONTENT_SETTING_ALLOW); + CheckPermissionStatus(PERMISSION_NOTIFICATIONS, PERMISSION_STATUS_GRANTED); + + SetPermission(CONTENT_SETTINGS_TYPE_MIDI_SYSEX, CONTENT_SETTING_ALLOW); + CheckPermissionStatus(PERMISSION_MIDI_SYSEX, PERMISSION_STATUS_GRANTED); + + SetPermission(CONTENT_SETTINGS_TYPE_PUSH_MESSAGING, CONTENT_SETTING_ALLOW); + CheckPermissionStatus(PERMISSION_PUSH_MESSAGING, PERMISSION_STATUS_GRANTED); + +#if defined(OS_ANDROID) + SetPermission(CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER, + CONTENT_SETTING_ALLOW); + CheckPermissionStatus(PERMISSION_PROTECTED_MEDIA, PERMISSION_STATUS_GRANTED); +#endif +} + +} // namespace chrome
diff --git a/chrome/browser/chrome_notification_types.h b/chrome/browser/chrome_notification_types.h index 38ed1b7..33d40455 100644 --- a/chrome/browser/chrome_notification_types.h +++ b/chrome/browser/chrome_notification_types.h
@@ -236,10 +236,6 @@ // the details is history::URLsDeletedDetails that lists the deleted URLs. NOTIFICATION_HISTORY_URLS_DELETED, - // Sent when a keyword search term is deleted. The source is the Profile and - // the details is history::KeywordSearchDeletedDetails. - NOTIFICATION_HISTORY_KEYWORD_SEARCH_TERM_DELETED, - // Sent by FaviconTabHelper when a tab's favicon has been successfully // updated. The details are a bool indicating whether the // NavigationEntry's favicon URL has changed since the previous @@ -625,15 +621,6 @@ // all error UIs should update. NOTIFICATION_GLOBAL_ERRORS_CHANGED, - // BrowsingDataRemover ---------------------------------------------------- - // Sent on the UI thread after BrowsingDataRemover has removed browsing data - // but before it has notified its explicit observers. The source is a - // Source<Profile> containing the profile in which browsing data was removed, - // and the detail is a BrowsingDataRemover::NotificationDetail containing the - // removal mask and the start of the removal timeframe with which - // BrowsingDataRemove::Remove was called. - NOTIFICATION_BROWSING_DATA_REMOVED, - // The user accepted or dismissed a SSL client authentication request. // The source is a Source<net::HttpNetworkSession>. Details is a // (std::pair<net::SSLCertRequestInfo*, net::X509Certificate*>).
diff --git a/chrome/browser/chrome_process_finder_win.cc b/chrome/browser/chrome_process_finder_win.cc index 52efec5..0fe8844 100644 --- a/chrome/browser/chrome_process_finder_win.cc +++ b/chrome/browser/chrome_process_finder_win.cc
@@ -11,7 +11,7 @@ #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/logging.h" -#include "base/process/process_handle.h" +#include "base/process/process.h" #include "base/process/process_info.h" #include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" @@ -112,45 +112,6 @@ if (!thread_id || !process_id) return NOTIFY_FAILED; -#if !defined(USE_AURA) - if (base::win::IsMetroProcess()) { - // Interesting corner case. We are launched as a metro process but we - // found another chrome running. Since metro enforces single instance then - // the other chrome must be desktop chrome and this must be a search charm - // activation. This scenario is unique; other cases should be properly - // handled by the delegate_execute which will not activate a second chrome. - base::string16 terms; - base::win::MetroLaunchType launch = base::win::GetMetroLaunchParams(&terms); - if (launch != base::win::METRO_SEARCH) { - LOG(WARNING) << "In metro mode, but and launch is " << launch; - } else { - std::string query = EscapeQueryParamValue(base::UTF16ToUTF8(terms), true); - std::string url = base::StringPrintf(kSearchUrl, query.c_str()); - SHELLEXECUTEINFOA sei = { sizeof(sei) }; - sei.fMask = SEE_MASK_FLAG_LOG_USAGE; - sei.nShow = SW_SHOWNORMAL; - sei.lpFile = url.c_str(); - OutputDebugStringA(sei.lpFile); - sei.lpDirectory = ""; - ::ShellExecuteExA(&sei); - } - return NOTIFY_SUCCESS; - } - - base::win::ScopedHandle process_handle; - if (base::win::GetVersion() >= base::win::VERSION_WIN8 && - base::OpenProcessHandleWithAccess( - process_id, PROCESS_QUERY_INFORMATION, - process_handle.Receive())) { - // Receive() causes the process handle to be set in the destructor of the - // temporary receiver object, which does not happen until after the if - // statement is complete. So IsProcessImmersive() should only be checked - // as part of a separate if statement. - if (base::win::IsProcessImmersive(process_handle.Get())) - chrome::ActivateMetroChrome(); - } -#endif - base::CommandLine command_line(*base::CommandLine::ForCurrentProcess()); command_line.AppendSwitchASCII( switches::kOriginalProcessStartTime,
diff --git a/chrome/browser/chromeos/app_mode/app_session_lifetime.cc b/chrome/browser/chromeos/app_mode/app_session_lifetime.cc index fe40288d..741a1c1 100644 --- a/chrome/browser/chromeos/app_mode/app_session_lifetime.cc +++ b/chrome/browser/chromeos/app_mode/app_session_lifetime.cc
@@ -38,23 +38,24 @@ namespace { // AppWindowHandler watches for app window and exits the session when the -// last app window is closed. +// last window of a given app is closed. class AppWindowHandler : public AppWindowRegistry::Observer { public: AppWindowHandler() : window_registry_(NULL) {} ~AppWindowHandler() override {} - void Init(Profile* profile) { + void Init(Profile* profile, const std::string& app_id) { DCHECK(!window_registry_); window_registry_ = AppWindowRegistry::Get(profile); if (window_registry_) window_registry_->AddObserver(this); + app_id_ = app_id; } private: // extensions::AppWindowRegistry::Observer overrides: void OnAppWindowRemoved(AppWindow* app_window) override { - if (window_registry_->app_windows().empty()) { + if (window_registry_->GetAppWindowsForApp(app_id_).empty()) { if (DemoAppLauncher::IsDemoAppSession( user_manager::UserManager::Get()->GetActiveUser()->email())) { // If we were in demo mode, we disabled all our network technologies, @@ -72,6 +73,7 @@ } AppWindowRegistry* window_registry_; + std::string app_id_; DISALLOW_COPY_AND_ASSIGN(AppWindowHandler); }; @@ -121,7 +123,7 @@ void InitAppSession(Profile* profile, const std::string& app_id) { // Binds the session lifetime with app window counts. CHECK(app_window_handler == NULL); - app_window_handler.Get().Init(profile); + app_window_handler.Get().Init(profile, app_id); CHECK(browser_window_handler == NULL); browser_window_handler.Get();
diff --git a/chrome/browser/chromeos/app_mode/kiosk_app_data.cc b/chrome/browser/chromeos/app_mode/kiosk_app_data.cc index 0032590..2dc37c83 100644 --- a/chrome/browser/chromeos/app_mode/kiosk_app_data.cc +++ b/chrome/browser/chromeos/app_mode/kiosk_app_data.cc
@@ -19,6 +19,7 @@ #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/extension_util.h" +#include "chrome/browser/extensions/sandboxed_unpacker.h" #include "chrome/browser/extensions/webstore_data_fetcher.h" #include "chrome/browser/extensions/webstore_install_helper.h" #include "chrome/browser/image_decoder.h" @@ -84,6 +85,111 @@ } // namespace //////////////////////////////////////////////////////////////////////////////// +// KioskAppData::CrxLoader +// Loads meta data from crx file. + +class KioskAppData::CrxLoader : public extensions::SandboxedUnpackerClient { + public: + CrxLoader(const base::WeakPtr<KioskAppData>& client, + const base::FilePath& crx_file) + : client_(client), + crx_file_(crx_file), + success_(false) { + } + + void Start() { + base::SequencedWorkerPool* pool = BrowserThread::GetBlockingPool(); + base::SequencedWorkerPool::SequenceToken token = + pool->GetNamedSequenceToken("KioskAppData.CrxLoaderWorker"); + task_runner_ = pool->GetSequencedTaskRunnerWithShutdownBehavior( + token, + base::SequencedWorkerPool::SKIP_ON_SHUTDOWN); + task_runner_->PostTask(FROM_HERE, + base::Bind(&CrxLoader::StartOnBlockingPool, this)); + } + + bool success() const { return success_; } + const base::FilePath& crx_file() const { return crx_file_; } + const std::string& name() const { return name_; } + const SkBitmap& icon() const { return icon_; } + + private: + ~CrxLoader() override {}; + + // extensions::SandboxedUnpackerClient + void OnUnpackSuccess(const base::FilePath& temp_dir, + const base::FilePath& extension_root, + const base::DictionaryValue* original_manifest, + const extensions::Extension* extension, + const SkBitmap& install_icon) override { + DCHECK(task_runner_->RunsTasksOnCurrentThread()); + + success_ = true; + name_ = extension->name(); + icon_ = install_icon; + NotifyFinishedOnBlockingPool(); + } + void OnUnpackFailure(const base::string16& error) override { + DCHECK(task_runner_->RunsTasksOnCurrentThread()); + + success_ = false; + NotifyFinishedOnBlockingPool(); + } + + void StartOnBlockingPool() { + DCHECK(task_runner_->RunsTasksOnCurrentThread()); + + if (!temp_dir_.CreateUniqueTempDir()) { + success_ = false; + NotifyFinishedOnBlockingPool(); + return; + } + + scoped_refptr<extensions::SandboxedUnpacker> unpacker( + new extensions::SandboxedUnpacker(crx_file_, + extensions::Manifest::INTERNAL, + extensions::Extension::NO_FLAGS, + temp_dir_.path(), + task_runner_.get(), + this)); + unpacker->Start(); + } + + void NotifyFinishedOnBlockingPool() { + DCHECK(task_runner_->RunsTasksOnCurrentThread()); + + if (!temp_dir_.Delete()) { + LOG(WARNING) << "Can not delete temp directory at " + << temp_dir_.path().value(); + } + + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind(&CrxLoader::NotifyFinishedOnUIThread, this)); + } + + void NotifyFinishedOnUIThread() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + if (client_) + client_->OnCrxLoadFinished(this); + } + + base::WeakPtr<KioskAppData> client_; + base::FilePath crx_file_; + bool success_; + + scoped_refptr<base::SequencedTaskRunner> task_runner_; + base::ScopedTempDir temp_dir_; + + // Extracted meta data. + std::string name_; + SkBitmap icon_; + + DISALLOW_COPY_AND_ASSIGN(CrxLoader); +}; + +//////////////////////////////////////////////////////////////////////////////// // KioskAppData::IconLoader // Loads locally stored icon data and decode it. @@ -106,7 +212,7 @@ base::SequencedWorkerPool::SequenceToken token = pool->GetSequenceToken(); task_runner_ = pool->GetSequencedTaskRunnerWithShutdownBehavior( token, - base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN); + base::SequencedWorkerPool::SKIP_ON_SHUTDOWN); task_runner_->PostTask(FROM_HERE, base::Bind(&IconLoader::LoadOnBlockingPool, base::Unretained(this))); @@ -149,7 +255,7 @@ return; if (load_result_ == SUCCESS) - client_->OnIconLoadSuccess(raw_icon_, icon_); + client_->OnIconLoadSuccess(icon_); else client_->OnIconLoadFailure(); } @@ -313,10 +419,23 @@ base::Bind(&KioskAppData::OnExtensionIconLoaded, AsWeakPtr())); } +void KioskAppData::SetCachedCrx(const base::FilePath& crx_file) { + if (crx_file_ == crx_file) + return; + + crx_file_ = crx_file; + MaybeLoadFromCrx(); +} + bool KioskAppData::IsLoading() const { return status_ == STATUS_LOADING; } +bool KioskAppData::IsFromWebStore() const { + return update_url_.is_empty() || + extension_urls::IsWebstoreUpdateUrl(update_url_); +} + void KioskAppData::SetStatus(Status status) { if (status_ == status) return; @@ -380,13 +499,15 @@ } void KioskAppData::SetCache(const std::string& name, const SkBitmap& icon) { + name_ = name; + icon_ = gfx::ImageSkia::CreateFrom1xBitmap(icon); icon_.MakeThreadSafe(); std::vector<unsigned char> image_data; CHECK(gfx::PNGCodec::EncodeBGRASkBitmap(icon, false, &image_data)); - raw_icon_ = new base::RefCountedString; - raw_icon_->data().assign(image_data.begin(), image_data.end()); + scoped_refptr<base::RefCountedString> raw_icon(new base::RefCountedString); + raw_icon->data().assign(image_data.begin(), image_data.end()); base::FilePath cache_dir; if (delegate_) @@ -396,7 +517,7 @@ cache_dir.AppendASCII(app_id_).AddExtension(kIconFileExtension); BrowserThread::GetBlockingPool()->PostTask( FROM_HERE, - base::Bind(&SaveIconToLocalOnBlockingPool, icon_path, raw_icon_)); + base::Bind(&SaveIconToLocalOnBlockingPool, icon_path, raw_icon)); SetCache(name, icon_path); } @@ -413,11 +534,8 @@ SetStatus(STATUS_LOADED); } -void KioskAppData::OnIconLoadSuccess( - const scoped_refptr<base::RefCountedString>& raw_icon, - const gfx::ImageSkia& icon) { +void KioskAppData::OnIconLoadSuccess(const gfx::ImageSkia& icon) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - raw_icon_ = raw_icon; icon_ = icon; SetStatus(STATUS_LOADED); } @@ -437,6 +555,11 @@ } void KioskAppData::StartFetch() { + if (!IsFromWebStore()) { + MaybeLoadFromCrx(); + return; + } + webstore_fetcher_.reset(new extensions::WebstoreDataFetcher( this, GetRequestContextGetter(), @@ -502,4 +625,31 @@ return true; } +void KioskAppData::MaybeLoadFromCrx() { + if (status_ == STATUS_LOADED || crx_file_.empty()) + return; + + scoped_refptr<CrxLoader> crx_loader(new CrxLoader(AsWeakPtr(), crx_file_)); + crx_loader->Start(); +} + +void KioskAppData::OnCrxLoadFinished(const CrxLoader* crx_loader) { + DCHECK(crx_loader); + + if (crx_loader->crx_file() != crx_file_) + return; + + if (!crx_loader->success()) { + SetStatus(STATUS_ERROR); + return; + } + + SkBitmap icon = crx_loader->icon(); + if (icon.empty()) + icon = *extensions::util::GetDefaultAppIcon().bitmap(); + SetCache(crx_loader->name(), icon); + + SetStatus(STATUS_LOADED); +} + } // namespace chromeos
diff --git a/chrome/browser/chromeos/app_mode/kiosk_app_data.h b/chrome/browser/chromeos/app_mode/kiosk_app_data.h index b429020e..44104ad 100644 --- a/chrome/browser/chromeos/app_mode/kiosk_app_data.h +++ b/chrome/browser/chromeos/app_mode/kiosk_app_data.h
@@ -17,10 +17,6 @@ class Profile; -namespace base { -class RefCountedString; -} - namespace extensions { class Extension; class WebstoreDataFetcher; @@ -66,20 +62,25 @@ // Loads app data from the app installed in the given profile. void LoadFromInstalledApp(Profile* profile, const extensions::Extension* app); + // Sets full path of the cache crx. The crx would be used to extract meta + // data for private apps. + void SetCachedCrx(const base::FilePath& crx_file); + // Returns true if web store data fetching is in progress. bool IsLoading() const; + // Returns true if the update url points to Webstore. + bool IsFromWebStore() const; + const std::string& app_id() const { return app_id_; } const std::string& user_id() const { return user_id_; } const std::string& name() const { return name_; } const GURL& update_url() const { return update_url_; } const gfx::ImageSkia& icon() const { return icon_; } - const base::RefCountedString* raw_icon() const { - return raw_icon_.get(); - } Status status() const { return status_; } private: + class CrxLoader; class IconLoader; class WebstoreDataParser; @@ -101,8 +102,7 @@ void OnExtensionIconLoaded(const gfx::Image& icon); // Callbacks for IconLoader. - void OnIconLoadSuccess(const scoped_refptr<base::RefCountedString>& raw_icon, - const gfx::ImageSkia& icon); + void OnIconLoadSuccess(const gfx::ImageSkia& icon); void OnIconLoadFailure(); // Callbacks for WebstoreDataParser @@ -125,6 +125,12 @@ const char* key, std::string* value); + // Extracts meta data from crx file when loading from Webstore and local + // cache fails. + void MaybeLoadFromCrx(); + + void OnCrxLoadFinished(const CrxLoader* crx_loader); + KioskAppDataDelegate* delegate_; // not owned. Status status_; @@ -133,11 +139,12 @@ std::string name_; GURL update_url_; gfx::ImageSkia icon_; - scoped_refptr<base::RefCountedString> raw_icon_; scoped_ptr<extensions::WebstoreDataFetcher> webstore_fetcher_; base::FilePath icon_path_; + base::FilePath crx_file_; + DISALLOW_COPY_AND_ASSIGN(KioskAppData); };
diff --git a/chrome/browser/chromeos/app_mode/kiosk_app_manager.cc b/chrome/browser/chromeos/app_mode/kiosk_app_manager.cc index e24758d..86affa2 100644 --- a/chrome/browser/chromeos/app_mode/kiosk_app_manager.cc +++ b/chrome/browser/chromeos/app_mode/kiosk_app_manager.cc
@@ -326,15 +326,6 @@ return true; } -const base::RefCountedString* KioskAppManager::GetAppRawIcon( - const std::string& app_id) const { - const KioskAppData* data = GetAppData(app_id); - if (!data) - return NULL; - - return data->raw_icon(); -} - bool KioskAppManager::GetDisableBailoutShortcut() const { bool enable; if (CrosSettings::Get()->GetBoolean( @@ -595,6 +586,12 @@ KioskAppData* app_data = GetAppDataMutable(id); if (!app_data) return; + + base::FilePath crx_path; + std::string version; + if (GetCachedCrx(id, &crx_path, &version)) + app_data->SetCachedCrx(crx_path); + FOR_EACH_OBSERVER(KioskAppManagerObserver, observers_, OnKioskExtensionLoadedInCache(id));
diff --git a/chrome/browser/chromeos/app_mode/kiosk_app_manager.h b/chrome/browser/chromeos/app_mode/kiosk_app_manager.h index 3e64926..0084d54 100644 --- a/chrome/browser/chromeos/app_mode/kiosk_app_manager.h +++ b/chrome/browser/chromeos/app_mode/kiosk_app_manager.h
@@ -138,10 +138,6 @@ // |app| is populated. Otherwise, return false. bool GetApp(const std::string& app_id, App* app) const; - // Gets the raw icon data for the given app id. Returns NULL if |app_id| - // is unknown. - const base::RefCountedString* GetAppRawIcon(const std::string& app_id) const; - // Gets whether the bailout shortcut is disabled. bool GetDisableBailoutShortcut() const;
diff --git a/chrome/browser/chromeos/drive/change_list_loader.h b/chrome/browser/chromeos/drive/change_list_loader.h index e0796fc6..9b951965 100644 --- a/chrome/browser/chromeos/drive/change_list_loader.h +++ b/chrome/browser/chromeos/drive/change_list_loader.h
@@ -27,7 +27,6 @@ namespace google_apis { class AboutResource; -class ResourceList; } // namespace google_apis namespace drive {
diff --git a/chrome/browser/chromeos/drive/drive_integration_service.cc b/chrome/browser/chromeos/drive/drive_integration_service.cc index 70dcced..293fd5f 100644 --- a/chrome/browser/chromeos/drive/drive_integration_service.cc +++ b/chrome/browser/chromeos/drive/drive_integration_service.cc
@@ -46,7 +46,6 @@ #include "content/public/browser/notification_service.h" #include "content/public/common/user_agent.h" #include "google_apis/drive/auth_service.h" -#include "google_apis/drive/gdata_wapi_url_generator.h" #include "storage/browser/fileapi/external_mount_points.h" #include "ui/base/l10n/l10n_util.h" @@ -240,7 +239,6 @@ blocking_task_runner_.get(), GURL(google_apis::DriveApiUrlGenerator::kBaseUrlForProduction), GURL(google_apis::DriveApiUrlGenerator::kBaseDownloadUrlForProduction), - GURL(google_apis::GDataWapiUrlGenerator::kBaseUrlForProduction), GetDriveUserAgent())); } scheduler_.reset(new JobScheduler(
diff --git a/chrome/browser/chromeos/drive/dummy_file_system.h b/chrome/browser/chromeos/drive/dummy_file_system.h index 16db475..cebfacfe 100644 --- a/chrome/browser/chromeos/drive/dummy_file_system.h +++ b/chrome/browser/chromeos/drive/dummy_file_system.h
@@ -75,7 +75,7 @@ int options, int at_most_num_matches, const SearchMetadataCallback& callback) override {} - void SearchByHashes(const std::vector<std::string>& hashes, + void SearchByHashes(const std::set<std::string>& hashes, const SearchByHashesCallback& callback) override {} void GetAvailableSpace(const GetAvailableSpaceCallback& callback) override {} void GetShareUrl(const base::FilePath& file_path,
diff --git a/chrome/browser/chromeos/drive/fake_file_system.cc b/chrome/browser/chromeos/drive/fake_file_system.cc index 87f2d91..0d5894a 100644 --- a/chrome/browser/chromeos/drive/fake_file_system.cc +++ b/chrome/browser/chromeos/drive/fake_file_system.cc
@@ -185,7 +185,7 @@ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); } -void FakeFileSystem::SearchByHashes(const std::vector<std::string>& hashes, +void FakeFileSystem::SearchByHashes(const std::set<std::string>& hashes, const SearchByHashesCallback& callback) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); }
diff --git a/chrome/browser/chromeos/drive/fake_file_system.h b/chrome/browser/chromeos/drive/fake_file_system.h index 87ba583..2fe2137 100644 --- a/chrome/browser/chromeos/drive/fake_file_system.h +++ b/chrome/browser/chromeos/drive/fake_file_system.h
@@ -103,7 +103,7 @@ int options, int at_most_num_matches, const SearchMetadataCallback& callback) override; - void SearchByHashes(const std::vector<std::string>& hashes, + void SearchByHashes(const std::set<std::string>& hashes, const SearchByHashesCallback& callback) override; void GetAvailableSpace(const GetAvailableSpaceCallback& callback) override; void GetShareUrl(const base::FilePath& file_path,
diff --git a/chrome/browser/chromeos/drive/file_system.cc b/chrome/browser/chromeos/drive/file_system.cc index 896845ca..f5f637b 100644 --- a/chrome/browser/chromeos/drive/file_system.cc +++ b/chrome/browser/chromeos/drive/file_system.cc
@@ -236,6 +236,32 @@ callback.Run(GDataToFileError(error)); } +// Checks if the |entry|'s hash is included in |hashes|. +bool CheckHashes(const std::set<std::string>& hashes, + const ResourceEntry& entry) { + return hashes.find(entry.file_specific_info().md5()) != hashes.end(); +} + +// Runs |callback| with |error| and the list of HashAndFilePath obtained from +// |original_result|. +void RunSearchByHashesCallback( + const SearchByHashesCallback& callback, + FileError error, + scoped_ptr<MetadataSearchResultVector> original_result) { + std::vector<HashAndFilePath> result; + if (error != FILE_ERROR_OK) { + callback.Run(error, result); + return; + } + for (const auto& search_result : *original_result) { + HashAndFilePath hash_and_path; + hash_and_path.hash = search_result.md5; + hash_and_path.path = search_result.path; + result.push_back(hash_and_path); + } + callback.Run(FILE_ERROR_OK, result); +} + } // namespace struct FileSystem::CreateDirectoryParams { @@ -773,18 +799,20 @@ if (pref_service_->GetBoolean(prefs::kDisableDriveHostedFiles)) options |= SEARCH_METADATA_EXCLUDE_HOSTED_DOCUMENTS; - drive::internal::SearchMetadata(blocking_task_runner_, - resource_metadata_, - query, - options, - at_most_num_matches, - callback); + drive::internal::SearchMetadata( + blocking_task_runner_, resource_metadata_, query, + base::Bind(&drive::internal::MatchesType, options), at_most_num_matches, + callback); } -void FileSystem::SearchByHashes(const std::vector<std::string>& hashes, +void FileSystem::SearchByHashes(const std::set<std::string>& hashes, const SearchByHashesCallback& callback) { - DCHECK(!callback.is_null()); - NOTIMPLEMENTED(); + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + drive::internal::SearchMetadata( + blocking_task_runner_, resource_metadata_, + /* any file name */ "", base::Bind(&CheckHashes, hashes), + std::numeric_limits<size_t>::max(), + base::Bind(&RunSearchByHashesCallback, callback)); } void FileSystem::OnFileChangedByOperation(const FileChange& changed_files) {
diff --git a/chrome/browser/chromeos/drive/file_system.h b/chrome/browser/chromeos/drive/file_system.h index 85e6e89d..25e5868 100644 --- a/chrome/browser/chromeos/drive/file_system.h +++ b/chrome/browser/chromeos/drive/file_system.h
@@ -83,7 +83,7 @@ int options, int at_most_num_matches, const SearchMetadataCallback& callback) override; - void SearchByHashes(const std::vector<std::string>& hashes, + void SearchByHashes(const std::set<std::string>& hashes, const SearchByHashesCallback& callback) override; void TransferFileFromLocalToRemote( const base::FilePath& local_src_file_path,
diff --git a/chrome/browser/chromeos/drive/file_system_interface.cc b/chrome/browser/chromeos/drive/file_system_interface.cc new file mode 100644 index 0000000..fb91a44 --- /dev/null +++ b/chrome/browser/chromeos/drive/file_system_interface.cc
@@ -0,0 +1,20 @@ +// Copyright 2015 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/drive/file_system_interface.h" + +namespace drive { + +MetadataSearchResult::MetadataSearchResult( + const base::FilePath& path, + bool is_directory, + const std::string& highlighted_base_name, + const std::string& md5) + : path(path), + is_directory(is_directory), + highlighted_base_name(highlighted_base_name), + md5(md5) { +} + +} // namespace drive
diff --git a/chrome/browser/chromeos/drive/file_system_interface.h b/chrome/browser/chromeos/drive/file_system_interface.h index 1a606a3..5f6cae0 100644 --- a/chrome/browser/chromeos/drive/file_system_interface.h +++ b/chrome/browser/chromeos/drive/file_system_interface.h
@@ -24,9 +24,7 @@ // browser. struct SearchResultInfo { SearchResultInfo(const base::FilePath& path, bool is_directory) - : path(path), - is_directory(is_directory) { - } + : path(path), is_directory(is_directory) {} base::FilePath path; bool is_directory; @@ -40,12 +38,10 @@ // Struct to represent a search result for SearchMetadata(). struct MetadataSearchResult { - MetadataSearchResult(const base::FilePath& in_path, + MetadataSearchResult(const base::FilePath& path, bool is_directory, - const std::string& in_highlighted_base_name) - : path(in_path), - is_directory(is_directory), - highlighted_base_name(in_highlighted_base_name) {} + const std::string& highlighted_base_name, + const std::string& md5); // The two members are used to create FileEntry object. base::FilePath path; @@ -61,6 +57,9 @@ // // Why <b> instead of <strong>? Because <b> is shorter. std::string highlighted_base_name; + + // MD5 hash of the file. + std::string md5; }; typedef std::vector<MetadataSearchResult> MetadataSearchResultVector; @@ -104,7 +103,7 @@ // Callback for SearchByHashesCallback. On success, vector contains hash and // corresponding files. The vector can include multiple entries for one hash. -typedef base::Callback<void(const std::vector<HashAndFilePath>&)> +typedef base::Callback<void(FileError, const std::vector<HashAndFilePath>&)> SearchByHashesCallback; // Used to open files from the file system. |file_path| is the path on the local @@ -397,7 +396,7 @@ // given |hashes|. The list of resource entries are passed to |callback|. The // item of the list can be null if the corresponding file is not found. // |callback| must not be null. - virtual void SearchByHashes(const std::vector<std::string>& hashes, + virtual void SearchByHashes(const std::set<std::string>& hashes, const SearchByHashesCallback& callback) = 0; // Fetches the user's Account Metadata to find out current quota information
diff --git a/chrome/browser/chromeos/drive/file_system_unittest.cc b/chrome/browser/chromeos/drive/file_system_unittest.cc index a16d98f..10c6daea 100644 --- a/chrome/browser/chromeos/drive/file_system_unittest.cc +++ b/chrome/browser/chromeos/drive/file_system_unittest.cc
@@ -54,6 +54,16 @@ quit.Run(); } +bool CompareHashAndFilePath(const HashAndFilePath& a, + const HashAndFilePath& b) { + const int result = a.hash.compare(b.hash); + if (result < 0) + return true; + if (result > 0) + return false; + return a.path.AsUTF8Unsafe().compare(b.path.AsUTF8Unsafe()) < 0; +} + // This class is used to record directory changes and examine them later. class MockDirectoryChangeObserver : public FileSystemObserver { public: @@ -249,7 +259,7 @@ file1.set_title("File1"); file1.set_resource_id("resource_id:File1"); file1.set_parent_local_id(root.local_id()); - file1.mutable_file_specific_info()->set_md5("md5"); + file1.mutable_file_specific_info()->set_md5("md5#1"); file1.mutable_file_info()->set_is_directory(false); file1.mutable_file_info()->set_size(1048576); ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry(file1, &local_id)); @@ -268,7 +278,7 @@ file2.set_title("File2"); file2.set_resource_id("resource_id:File2"); file2.set_parent_local_id(dir1_local_id); - file2.mutable_file_specific_info()->set_md5("md5"); + file2.mutable_file_specific_info()->set_md5("md5#2"); file2.mutable_file_info()->set_is_directory(false); file2.mutable_file_info()->set_size(555); ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry(file2, &local_id)); @@ -287,7 +297,7 @@ file3.set_title("File3"); file3.set_resource_id("resource_id:File3"); file3.set_parent_local_id(dir2_local_id); - file3.mutable_file_specific_info()->set_md5("md5"); + file3.mutable_file_specific_info()->set_md5("md5#2"); file3.mutable_file_info()->set_is_directory(false); file3.mutable_file_info()->set_size(12345); ASSERT_EQ(FILE_ERROR_OK, resource_metadata->AddEntry(file3, &local_id)); @@ -316,6 +326,53 @@ scoped_ptr<FileSystem> file_system_; }; +TEST_F(FileSystemTest, SearchByHashes) { + ASSERT_NO_FATAL_FAILURE(SetUpTestFileSystem(USE_SERVER_TIMESTAMP)); + + std::set<std::string> hashes; + FileError error; + std::vector<HashAndFilePath> results; + + hashes.insert("md5#1"); + file_system_->SearchByHashes( + hashes, + google_apis::test_util::CreateCopyResultCallback(&error, &results)); + content::RunAllBlockingPoolTasksUntilIdle(); + EXPECT_EQ(FILE_ERROR_OK, error); + ASSERT_EQ(1u, results.size()); + EXPECT_EQ(FILE_PATH_LITERAL("drive/root/File1"), results[0].path.value()); + + hashes.clear(); + hashes.insert("md5#2"); + file_system_->SearchByHashes( + hashes, + google_apis::test_util::CreateCopyResultCallback(&error, &results)); + content::RunAllBlockingPoolTasksUntilIdle(); + EXPECT_EQ(FILE_ERROR_OK, error); + ASSERT_EQ(2u, results.size()); + std::sort(results.begin(), results.end(), &CompareHashAndFilePath); + EXPECT_EQ(FILE_PATH_LITERAL("drive/root/Dir1/File2"), + results[0].path.value()); + EXPECT_EQ(FILE_PATH_LITERAL("drive/root/Dir1/SubDir2/File3"), + results[1].path.value()); + + hashes.clear(); + hashes.insert("md5#1"); + hashes.insert("md5#2"); + file_system_->SearchByHashes( + hashes, + google_apis::test_util::CreateCopyResultCallback(&error, &results)); + content::RunAllBlockingPoolTasksUntilIdle(); + EXPECT_EQ(FILE_ERROR_OK, error); + ASSERT_EQ(3u, results.size()); + std::sort(results.begin(), results.end(), &CompareHashAndFilePath); + EXPECT_EQ(FILE_PATH_LITERAL("drive/root/File1"), results[0].path.value()); + EXPECT_EQ(FILE_PATH_LITERAL("drive/root/Dir1/File2"), + results[1].path.value()); + EXPECT_EQ(FILE_PATH_LITERAL("drive/root/Dir1/SubDir2/File3"), + results[2].path.value()); +} + TEST_F(FileSystemTest, Copy) { base::FilePath src_file_path(FILE_PATH_LITERAL("drive/root/File 1.txt")); base::FilePath dest_file_path(FILE_PATH_LITERAL("drive/root/Copied.txt"));
diff --git a/chrome/browser/chromeos/drive/fileapi/async_file_util.cc b/chrome/browser/chromeos/drive/fileapi/async_file_util.cc index fa80c0a..9adf7871 100644 --- a/chrome/browser/chromeos/drive/fileapi/async_file_util.cc +++ b/chrome/browser/chromeos/drive/fileapi/async_file_util.cc
@@ -13,9 +13,9 @@ #include "chrome/browser/chromeos/drive/fileapi/fileapi_worker.h" #include "content/public/browser/browser_thread.h" #include "google_apis/drive/task_util.h" +#include "storage/browser/blob/shareable_file_reference.h" #include "storage/browser/fileapi/file_system_operation_context.h" #include "storage/browser/fileapi/file_system_url.h" -#include "storage/common/blob/shareable_file_reference.h" using content::BrowserThread;
diff --git a/chrome/browser/chromeos/drive/fileapi/fileapi_worker.h b/chrome/browser/chromeos/drive/fileapi/fileapi_worker.h index 4edbd44..e6d62057 100644 --- a/chrome/browser/chromeos/drive/fileapi/fileapi_worker.h +++ b/chrome/browser/chromeos/drive/fileapi/fileapi_worker.h
@@ -25,7 +25,7 @@ #include "base/callback_forward.h" #include "base/memory/weak_ptr.h" #include "chrome/browser/chromeos/drive/file_errors.h" -#include "storage/common/blob/scoped_file.h" +#include "storage/browser/blob/scoped_file.h" namespace base { class FilePath;
diff --git a/chrome/browser/chromeos/drive/search_metadata.cc b/chrome/browser/chromeos/drive/search_metadata.cc index 379eb39..1ba2763 100644 --- a/chrome/browser/chromeos/drive/search_metadata.cc +++ b/chrome/browser/chromeos/drive/search_metadata.cc
@@ -142,43 +142,6 @@ std::map<std::string, bool> is_hiding_child_; }; -// Returns true if |entry| is eligible for the search |options| and should be -// tested for the match with the query. If -// SEARCH_METADATA_EXCLUDE_HOSTED_DOCUMENTS is requested, the hosted documents -// are skipped. If SEARCH_METADATA_EXCLUDE_DIRECTORIES is requested, the -// directories are skipped. If SEARCH_METADATA_SHARED_WITH_ME is requested, only -// the entries with shared-with-me label will be tested. If -// SEARCH_METADATA_OFFLINE is requested, only hosted documents and cached files -// match with the query. This option can not be used with other options. -bool IsEligibleEntry(const ResourceEntry& entry, int options) { - if ((options & SEARCH_METADATA_EXCLUDE_HOSTED_DOCUMENTS) && - entry.file_specific_info().is_hosted_document()) - return false; - - if ((options & SEARCH_METADATA_EXCLUDE_DIRECTORIES) && - entry.file_info().is_directory()) - return false; - - if (options & SEARCH_METADATA_SHARED_WITH_ME) - return entry.shared_with_me(); - - if (options & SEARCH_METADATA_OFFLINE) { - if (entry.file_specific_info().is_hosted_document()) { - // Not all hosted documents are cached by Drive offline app. - // http://support.google.com/drive/bin/answer.py?hl=en&answer=1628467 - std::string mime_type = entry.file_specific_info().content_mime_type(); - return mime_type == drive::util::kGoogleDocumentMimeType || - mime_type == drive::util::kGoogleSpreadsheetMimeType || - mime_type == drive::util::kGooglePresentationMimeType || - mime_type == drive::util::kGoogleDrawingMimeType; - } else { - return entry.file_specific_info().cache_state().is_present(); - } - } - - return true; -} - // Used to implement SearchMetadata. // Adds entry to the result when appropriate. // In particular, if |query| is non-null, only adds files with the name matching @@ -187,11 +150,11 @@ ResourceMetadata* resource_metadata, ResourceMetadata::Iterator* it, base::i18n::FixedPatternStringSearchIgnoringCaseAndAccents* query, - int options, + const SearchMetadataPredicate& predicate, size_t at_most_num_matches, HiddenEntryClassifier* hidden_entry_classifier, - ScopedPriorityQueue<ResultCandidate, - ResultCandidateComparator>* result_candidates) { + ScopedPriorityQueue<ResultCandidate, ResultCandidateComparator>* + result_candidates) { DCHECK_GE(at_most_num_matches, result_candidates->size()); const ResourceEntry& entry = it->GetValue(); @@ -207,7 +170,7 @@ // |options| and matches the query. The base name of the entry must // contain |query| to match the query. std::string highlighted; - if (!IsEligibleEntry(entry, options) || + if (!predicate.Run(entry) || (query && !FindAndHighlight(entry.base_name(), query, &highlighted))) return FILE_ERROR_OK; @@ -227,7 +190,7 @@ // Implements SearchMetadata(). FileError SearchMetadataOnBlockingPool(ResourceMetadata* resource_metadata, const std::string& query_text, - int options, + const SearchMetadataPredicate& predicate, int at_most_num_matches, MetadataSearchResultVector* results) { ScopedPriorityQueue<ResultCandidate, @@ -249,12 +212,10 @@ // Iterate over entries. scoped_ptr<ResourceMetadata::Iterator> it = resource_metadata->GetIterator(); for (; !it->IsAtEnd(); it->Advance()) { - FileError error = MaybeAddEntryToResult(resource_metadata, it.get(), - query_text.empty() ? NULL : &query, - options, - at_most_num_matches, - &hidden_entry_classifier, - &result_candidates); + FileError error = MaybeAddEntryToResult( + resource_metadata, it.get(), query_text.empty() ? NULL : &query, + predicate, at_most_num_matches, &hidden_entry_classifier, + &result_candidates); if (error != FILE_ERROR_OK) return error; } @@ -271,7 +232,8 @@ return error; bool is_directory = candidate.entry.file_info().is_directory(); results->push_back(MetadataSearchResult( - path, is_directory, candidate.highlighted_base_name)); + path, is_directory, candidate.highlighted_base_name, + candidate.entry.file_specific_info().md5())); } // Reverse the order here because |result_candidates| puts the most @@ -300,11 +262,10 @@ scoped_refptr<base::SequencedTaskRunner> blocking_task_runner, ResourceMetadata* resource_metadata, const std::string& query, - int options, - int at_most_num_matches, + const SearchMetadataPredicate& predicate, + size_t at_most_num_matches, const SearchMetadataCallback& callback) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - DCHECK_LE(0, at_most_num_matches); DCHECK(!callback.is_null()); const base::TimeTicks start_time = base::TimeTicks::Now(); @@ -312,18 +273,41 @@ scoped_ptr<MetadataSearchResultVector> results( new MetadataSearchResultVector); MetadataSearchResultVector* results_ptr = results.get(); - base::PostTaskAndReplyWithResult(blocking_task_runner.get(), - FROM_HERE, - base::Bind(&SearchMetadataOnBlockingPool, - resource_metadata, - query, - options, - at_most_num_matches, - results_ptr), - base::Bind(&RunSearchMetadataCallback, - callback, - start_time, - base::Passed(&results))); + base::PostTaskAndReplyWithResult( + blocking_task_runner.get(), FROM_HERE, + base::Bind(&SearchMetadataOnBlockingPool, resource_metadata, query, + predicate, at_most_num_matches, results_ptr), + base::Bind(&RunSearchMetadataCallback, callback, start_time, + base::Passed(&results))); +} + +bool MatchesType(int options, const ResourceEntry& entry) { + if ((options & SEARCH_METADATA_EXCLUDE_HOSTED_DOCUMENTS) && + entry.file_specific_info().is_hosted_document()) + return false; + + if ((options & SEARCH_METADATA_EXCLUDE_DIRECTORIES) && + entry.file_info().is_directory()) + return false; + + if (options & SEARCH_METADATA_SHARED_WITH_ME) + return entry.shared_with_me(); + + if (options & SEARCH_METADATA_OFFLINE) { + if (entry.file_specific_info().is_hosted_document()) { + // Not all hosted documents are cached by Drive offline app. + // http://support.google.com/drive/bin/answer.py?hl=en&answer=1628467 + std::string mime_type = entry.file_specific_info().content_mime_type(); + return mime_type == drive::util::kGoogleDocumentMimeType || + mime_type == drive::util::kGoogleSpreadsheetMimeType || + mime_type == drive::util::kGooglePresentationMimeType || + mime_type == drive::util::kGoogleDrawingMimeType; + } else { + return entry.file_specific_info().cache_state().is_present(); + } + } + + return true; } bool FindAndHighlight(
diff --git a/chrome/browser/chromeos/drive/search_metadata.h b/chrome/browser/chromeos/drive/search_metadata.h index e4f140d..2acb2819 100644 --- a/chrome/browser/chromeos/drive/search_metadata.h +++ b/chrome/browser/chromeos/drive/search_metadata.h
@@ -20,6 +20,8 @@ class ResourceMetadata; +typedef base::Callback<bool(const ResourceEntry&)> SearchMetadataPredicate; + // Searches the local resource metadata, and returns the entries // |at_most_num_matches| that contain |query| in their base names. Search is // done in a case-insensitive fashion. The eligible entries are selected based @@ -31,10 +33,20 @@ scoped_refptr<base::SequencedTaskRunner> blocking_task_runner, ResourceMetadata* resource_metadata, const std::string& query, - int search_options, - int at_most_num_matches, + const SearchMetadataPredicate& predicate, + size_t at_most_num_matches, const SearchMetadataCallback& callback); +// Returns true if |entry| is eligible for the search |options| and should be +// tested for the match with the query. If +// SEARCH_METADATA_EXCLUDE_HOSTED_DOCUMENTS is requested, the hosted documents +// are skipped. If SEARCH_METADATA_EXCLUDE_DIRECTORIES is requested, the +// directories are skipped. If SEARCH_METADATA_SHARED_WITH_ME is requested, only +// the entries with shared-with-me label will be tested. If +// SEARCH_METADATA_OFFLINE is requested, only hosted documents and cached files +// match with the query. This option can not be used with other options. +bool MatchesType(int options, const ResourceEntry& entry); + // Finds |query| in |text| while ignoring cases or accents. Cases of non-ASCII // characters are also ignored; they are compared in the 'Primary Level' of // http://userguide.icu-project.org/collation/concepts.
diff --git a/chrome/browser/chromeos/drive/search_metadata_unittest.cc b/chrome/browser/chromeos/drive/search_metadata_unittest.cc index c0f72af..08e3c6f 100644 --- a/chrome/browser/chromeos/drive/search_metadata_unittest.cc +++ b/chrome/browser/chromeos/drive/search_metadata_unittest.cc
@@ -162,13 +162,11 @@ FileError error = FILE_ERROR_FAILED; scoped_ptr<MetadataSearchResultVector> result; - SearchMetadata(base::MessageLoopProxy::current(), - resource_metadata_.get(), - "NonExistent", - SEARCH_METADATA_ALL, - kDefaultAtMostNumMatches, - google_apis::test_util::CreateCopyResultCallback( - &error, &result)); + SearchMetadata( + base::MessageLoopProxy::current(), resource_metadata_.get(), + "NonExistent", base::Bind(&MatchesType, SEARCH_METADATA_ALL), + kDefaultAtMostNumMatches, + google_apis::test_util::CreateCopyResultCallback(&error, &result)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(FILE_ERROR_OK, error); ASSERT_TRUE(result); @@ -179,13 +177,11 @@ FileError error = FILE_ERROR_FAILED; scoped_ptr<MetadataSearchResultVector> result; - SearchMetadata(base::MessageLoopProxy::current(), - resource_metadata_.get(), - "SubDirectory File 1.txt", - SEARCH_METADATA_ALL, - kDefaultAtMostNumMatches, - google_apis::test_util::CreateCopyResultCallback( - &error, &result)); + SearchMetadata( + base::MessageLoopProxy::current(), resource_metadata_.get(), + "SubDirectory File 1.txt", base::Bind(&MatchesType, SEARCH_METADATA_ALL), + kDefaultAtMostNumMatches, + google_apis::test_util::CreateCopyResultCallback(&error, &result)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(FILE_ERROR_OK, error); ASSERT_TRUE(result); @@ -201,13 +197,11 @@ scoped_ptr<MetadataSearchResultVector> result; // The query is all in lower case. - SearchMetadata(base::MessageLoopProxy::current(), - resource_metadata_.get(), - "subdirectory file 1.txt", - SEARCH_METADATA_ALL, - kDefaultAtMostNumMatches, - google_apis::test_util::CreateCopyResultCallback( - &error, &result)); + SearchMetadata( + base::MessageLoopProxy::current(), resource_metadata_.get(), + "subdirectory file 1.txt", base::Bind(&MatchesType, SEARCH_METADATA_ALL), + kDefaultAtMostNumMatches, + google_apis::test_util::CreateCopyResultCallback(&error, &result)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(FILE_ERROR_OK, error); ASSERT_TRUE(result); @@ -220,13 +214,10 @@ FileError error = FILE_ERROR_FAILED; scoped_ptr<MetadataSearchResultVector> result; - SearchMetadata(base::MessageLoopProxy::current(), - resource_metadata_.get(), - "SubDir", - SEARCH_METADATA_ALL, - kDefaultAtMostNumMatches, - google_apis::test_util::CreateCopyResultCallback( - &error, &result)); + SearchMetadata( + base::MessageLoopProxy::current(), resource_metadata_.get(), "SubDir", + base::Bind(&MatchesType, SEARCH_METADATA_ALL), kDefaultAtMostNumMatches, + google_apis::test_util::CreateCopyResultCallback(&error, &result)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(FILE_ERROR_OK, error); ASSERT_TRUE(result); @@ -246,13 +237,11 @@ // There are two files matching "SubDir" but only one file should be // returned. - SearchMetadata(base::MessageLoopProxy::current(), - resource_metadata_.get(), - "SubDir", - SEARCH_METADATA_ALL, - 1, // at_most_num_matches - google_apis::test_util::CreateCopyResultCallback( - &error, &result)); + SearchMetadata( + base::MessageLoopProxy::current(), resource_metadata_.get(), "SubDir", + base::Bind(&MatchesType, SEARCH_METADATA_ALL), + 1, // at_most_num_matches + google_apis::test_util::CreateCopyResultCallback(&error, &result)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(FILE_ERROR_OK, error); ASSERT_TRUE(result); @@ -265,13 +254,11 @@ FileError error = FILE_ERROR_FAILED; scoped_ptr<MetadataSearchResultVector> result; - SearchMetadata(base::MessageLoopProxy::current(), - resource_metadata_.get(), - "Directory 1", - SEARCH_METADATA_ALL, - kDefaultAtMostNumMatches, - google_apis::test_util::CreateCopyResultCallback( - &error, &result)); + SearchMetadata( + base::MessageLoopProxy::current(), resource_metadata_.get(), + "Directory 1", base::Bind(&MatchesType, SEARCH_METADATA_ALL), + kDefaultAtMostNumMatches, + google_apis::test_util::CreateCopyResultCallback(&error, &result)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(FILE_ERROR_OK, error); ASSERT_TRUE(result); @@ -283,13 +270,10 @@ FileError error = FILE_ERROR_FAILED; scoped_ptr<MetadataSearchResultVector> result; - SearchMetadata(base::MessageLoopProxy::current(), - resource_metadata_.get(), - "Document", - SEARCH_METADATA_ALL, - kDefaultAtMostNumMatches, - google_apis::test_util::CreateCopyResultCallback( - &error, &result)); + SearchMetadata( + base::MessageLoopProxy::current(), resource_metadata_.get(), "Document", + base::Bind(&MatchesType, SEARCH_METADATA_ALL), kDefaultAtMostNumMatches, + google_apis::test_util::CreateCopyResultCallback(&error, &result)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(FILE_ERROR_OK, error); ASSERT_TRUE(result); @@ -303,13 +287,11 @@ FileError error = FILE_ERROR_FAILED; scoped_ptr<MetadataSearchResultVector> result; - SearchMetadata(base::MessageLoopProxy::current(), - resource_metadata_.get(), - "Document", - SEARCH_METADATA_EXCLUDE_HOSTED_DOCUMENTS, - kDefaultAtMostNumMatches, - google_apis::test_util::CreateCopyResultCallback( - &error, &result)); + SearchMetadata( + base::MessageLoopProxy::current(), resource_metadata_.get(), "Document", + base::Bind(&MatchesType, SEARCH_METADATA_EXCLUDE_HOSTED_DOCUMENTS), + kDefaultAtMostNumMatches, + google_apis::test_util::CreateCopyResultCallback(&error, &result)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(FILE_ERROR_OK, error); ASSERT_TRUE(result); @@ -320,13 +302,11 @@ FileError error = FILE_ERROR_FAILED; scoped_ptr<MetadataSearchResultVector> result; - SearchMetadata(base::MessageLoopProxy::current(), - resource_metadata_.get(), - "", - SEARCH_METADATA_SHARED_WITH_ME, - kDefaultAtMostNumMatches, - google_apis::test_util::CreateCopyResultCallback( - &error, &result)); + SearchMetadata( + base::MessageLoopProxy::current(), resource_metadata_.get(), "", + base::Bind(&MatchesType, SEARCH_METADATA_SHARED_WITH_ME), + kDefaultAtMostNumMatches, + google_apis::test_util::CreateCopyResultCallback(&error, &result)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(FILE_ERROR_OK, error); ASSERT_TRUE(result); @@ -339,13 +319,11 @@ FileError error = FILE_ERROR_FAILED; scoped_ptr<MetadataSearchResultVector> result; - SearchMetadata(base::MessageLoopProxy::current(), - resource_metadata_.get(), - "excludeDir-test", - SEARCH_METADATA_ALL, - kDefaultAtMostNumMatches, - google_apis::test_util::CreateCopyResultCallback( - &error, &result)); + SearchMetadata( + base::MessageLoopProxy::current(), resource_metadata_.get(), + "excludeDir-test", base::Bind(&MatchesType, SEARCH_METADATA_ALL), + kDefaultAtMostNumMatches, + google_apis::test_util::CreateCopyResultCallback(&error, &result)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(FILE_ERROR_OK, error); @@ -362,13 +340,12 @@ FileError error = FILE_ERROR_FAILED; scoped_ptr<MetadataSearchResultVector> result; - SearchMetadata(base::MessageLoopProxy::current(), - resource_metadata_.get(), - "excludeDir-test", - SEARCH_METADATA_EXCLUDE_DIRECTORIES, - kDefaultAtMostNumMatches, - google_apis::test_util::CreateCopyResultCallback( - &error, &result)); + SearchMetadata( + base::MessageLoopProxy::current(), resource_metadata_.get(), + "excludeDir-test", + base::Bind(&MatchesType, SEARCH_METADATA_EXCLUDE_DIRECTORIES), + kDefaultAtMostNumMatches, + google_apis::test_util::CreateCopyResultCallback(&error, &result)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(FILE_ERROR_OK, error); @@ -387,13 +364,10 @@ scoped_ptr<MetadataSearchResultVector> result; const std::string query = kQueries[i]; - SearchMetadata(base::MessageLoopProxy::current(), - resource_metadata_.get(), - query, - SEARCH_METADATA_ALL, - kDefaultAtMostNumMatches, - google_apis::test_util::CreateCopyResultCallback( - &error, &result)); + SearchMetadata( + base::MessageLoopProxy::current(), resource_metadata_.get(), query, + base::Bind(&MatchesType, SEARCH_METADATA_ALL), kDefaultAtMostNumMatches, + google_apis::test_util::CreateCopyResultCallback(&error, &result)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(FILE_ERROR_OK, error); @@ -406,13 +380,11 @@ FileError error = FILE_ERROR_FAILED; scoped_ptr<MetadataSearchResultVector> result; - SearchMetadata(base::MessageLoopProxy::current(), - resource_metadata_.get(), - "", - SEARCH_METADATA_OFFLINE, - kDefaultAtMostNumMatches, - google_apis::test_util::CreateCopyResultCallback( - &error, &result)); + SearchMetadata( + base::MessageLoopProxy::current(), resource_metadata_.get(), "", + base::Bind(&MatchesType, SEARCH_METADATA_OFFLINE), + kDefaultAtMostNumMatches, + google_apis::test_util::CreateCopyResultCallback(&error, &result)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(FILE_ERROR_OK, error); ASSERT_EQ(3U, result->size());
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc index ba89eb1..b7b52fa 100644 --- a/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc +++ b/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/chromeos/extensions/file_manager/private_api_file_system.h" #include <sys/statvfs.h> +#include <set> #include "base/posix/eintr_wrapper.h" #include "base/strings/string_number_conversions.h" @@ -772,17 +773,41 @@ return false; } + std::set<std::string> hashes(params->hash_list.begin(), + params->hash_list.end()); file_system->SearchByHashes( - params->hash_list, + hashes, base::Bind( &FileManagerPrivateSearchFilesByHashesFunction::OnSearchByHashes, - this)); + this, hashes)); return true; } void FileManagerPrivateSearchFilesByHashesFunction::OnSearchByHashes( - const std::vector<drive::HashAndFilePath>& results) { - NOTIMPLEMENTED(); + const std::set<std::string>& hashes, + drive::FileError error, + const std::vector<drive::HashAndFilePath>& search_results) { + if (error != drive::FileError::FILE_ERROR_OK) { + SendResponse(false); + return; + } + + scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue()); + for (const auto& hash : hashes) { + result->SetWithoutPathExpansion(hash, + make_scoped_ptr(new base::ListValue())); + } + + for (const auto& hashAndPath : search_results) { + DCHECK(result->HasKey(hashAndPath.hash)); + base::ListValue* list; + result->GetListWithoutPathExpansion(hashAndPath.hash, &list); + list->AppendString( + file_manager::util::ConvertDrivePathToFileSystemUrl( + GetProfile(), hashAndPath.path, extension_id()).spec()); + } + SetResult(result.release()); + SendResponse(true); } } // namespace extensions
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.h b/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.h index c085122..5e3838ed 100644 --- a/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.h +++ b/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.h
@@ -260,9 +260,13 @@ ~FileManagerPrivateSearchFilesByHashesFunction() override {} private: - void OnSearchByHashes(const std::vector<drive::HashAndFilePath>& results); - + // AsyncExtensionFunction overrides. bool RunAsync() override; + + // Sends a response with |results| to the extension. + void OnSearchByHashes(const std::set<std::string>& hashes, + drive::FileError error, + const std::vector<drive::HashAndFilePath>& results); }; } // namespace extensions
diff --git a/chrome/browser/chromeos/extensions/file_system_provider/file_system_provider_api.h b/chrome/browser/chromeos/extensions/file_system_provider/file_system_provider_api.h index 592bb6e..224ac9a 100644 --- a/chrome/browser/chromeos/extensions/file_system_provider/file_system_provider_api.h +++ b/chrome/browser/chromeos/extensions/file_system_provider/file_system_provider_api.h
@@ -46,7 +46,7 @@ protected: ~FileSystemProviderGetFunction() override {} - virtual bool RunSync() override; + bool RunSync() override; }; class FileSystemProviderNotifyFunction : public ChromeAsyncExtensionFunction {
diff --git a/chrome/browser/chromeos/file_manager/snapshot_manager.cc b/chrome/browser/chromeos/file_manager/snapshot_manager.cc index d25c7a9..5ebb08a9 100644 --- a/chrome/browser/chromeos/file_manager/snapshot_manager.cc +++ b/chrome/browser/chromeos/file_manager/snapshot_manager.cc
@@ -11,8 +11,8 @@ #include "chrome/browser/profiles/profile.h" #include "content/public/browser/browser_thread.h" #include "google_apis/drive/task_util.h" +#include "storage/browser/blob/shareable_file_reference.h" #include "storage/browser/fileapi/file_system_context.h" -#include "storage/common/blob/shareable_file_reference.h" #include "third_party/cros_system_api/constants/cryptohome.h" namespace file_manager {
diff --git a/chrome/browser/chromeos/file_system_provider/fileapi/provider_async_file_util.cc b/chrome/browser/chromeos/file_system_provider/fileapi/provider_async_file_util.cc index 6fa9108..7ef074a3 100644 --- a/chrome/browser/chromeos/file_system_provider/fileapi/provider_async_file_util.cc +++ b/chrome/browser/chromeos/file_system_provider/fileapi/provider_async_file_util.cc
@@ -11,9 +11,9 @@ #include "chrome/browser/chromeos/file_system_provider/mount_path_util.h" #include "chrome/browser/chromeos/file_system_provider/provided_file_system_interface.h" #include "content/public/browser/browser_thread.h" +#include "storage/browser/blob/shareable_file_reference.h" #include "storage/browser/fileapi/file_system_operation_context.h" #include "storage/browser/fileapi/file_system_url.h" -#include "storage/common/blob/shareable_file_reference.h" using content::BrowserThread;
diff --git a/chrome/browser/chromeos/file_system_provider/fileapi/provider_async_file_util_unittest.cc b/chrome/browser/chromeos/file_system_provider/fileapi/provider_async_file_util_unittest.cc index 7015bf1..f3789cf 100644 --- a/chrome/browser/chromeos/file_system_provider/fileapi/provider_async_file_util_unittest.cc +++ b/chrome/browser/chromeos/file_system_provider/fileapi/provider_async_file_util_unittest.cc
@@ -22,11 +22,11 @@ #include "content/public/test/test_browser_thread_bundle.h" #include "content/public/test/test_file_system_context.h" #include "extensions/browser/extension_registry.h" +#include "storage/browser/blob/shareable_file_reference.h" #include "storage/browser/fileapi/async_file_util.h" #include "storage/browser/fileapi/external_mount_points.h" #include "storage/browser/fileapi/file_system_context.h" #include "storage/browser/fileapi/file_system_url.h" -#include "storage/common/blob/shareable_file_reference.h" #include "testing/gtest/include/gtest/gtest.h" namespace chromeos {
diff --git a/chrome/browser/chromeos/input_method/input_method_engine.cc b/chrome/browser/chromeos/input_method/input_method_engine.cc index 83f1e42..2195246b 100644 --- a/chrome/browser/chromeos/input_method/input_method_engine.cc +++ b/chrome/browser/chromeos/input_method/input_method_engine.cc
@@ -481,9 +481,6 @@ return false; } - if (offset < 0 && static_cast<size_t>(-1 * offset) != size_t(number_of_chars)) - return false; // Currently we can only support preceding text. - // TODO(nona): Return false if there is ongoing composition. IMEInputContextHandlerInterface* input_context =
diff --git a/chrome/browser/chromeos/login/chrome_restart_request.cc b/chrome/browser/chromeos/login/chrome_restart_request.cc index 16b8fd2..36bc3a5c 100644 --- a/chrome/browser/chromeos/login/chrome_restart_request.cc +++ b/chrome/browser/chromeos/login/chrome_restart_request.cc
@@ -99,12 +99,11 @@ ::switches::kDisableDisplayList2dCanvas, ::switches::kEnableDisplayList2dCanvas, ::switches::kForceDisplayList2dCanvas, - ::switches::kEnableEncryptedMedia, + ::switches::kDisableEncryptedMedia, ::switches::kDisableGpuSandbox, ::switches::kEnableDistanceFieldText, ::switches::kEnableGpuRasterization, ::switches::kEnableImageColorProfiles, - ::switches::kEnableImplSidePainting, ::switches::kEnableLogging, ::switches::kEnableLowResTiling, ::switches::kEnableOneCopy,
diff --git a/chrome/browser/chromeos/login/enrollment/auto_enrollment_controller.cc b/chrome/browser/chromeos/login/enrollment/auto_enrollment_controller.cc index ad3dc0c4..f028b46 100644 --- a/chrome/browser/chromeos/login/enrollment/auto_enrollment_controller.cc +++ b/chrome/browser/chromeos/login/enrollment/auto_enrollment_controller.cc
@@ -86,7 +86,16 @@ system::StatisticsProvider::GetInstance()->GetMachineStatistic( system::kFirmwareTypeKey, &firmware_type) && firmware_type == system::kFirmwareTypeValueNonchrome; - return non_chrome_firmware ? MODE_NONE : MODE_FORCED_RE_ENROLLMENT; + + std::string write_protect_switch_boot; + const bool write_protect_switch_off = + system::StatisticsProvider::GetInstance()->GetMachineStatistic( + system::kWriteProtectSwitchBootKey, &write_protect_switch_boot) && + write_protect_switch_boot == system::kWriteProtectSwitchBootValueOff; + + return (non_chrome_firmware || write_protect_switch_off) + ? MODE_NONE + : MODE_FORCED_RE_ENROLLMENT; #else return MODE_NONE; #endif
diff --git a/chrome/browser/chromeos/login/kiosk_browsertest.cc b/chrome/browser/chromeos/login/kiosk_browsertest.cc index 20623aa..079e937 100644 --- a/chrome/browser/chromeos/login/kiosk_browsertest.cc +++ b/chrome/browser/chromeos/login/kiosk_browsertest.cc
@@ -288,6 +288,113 @@ DISALLOW_COPY_AND_ASSIGN(KioskFakeDiskMountManager); }; +class AppDataLoadWaiter : public KioskAppManagerObserver { + public: + AppDataLoadWaiter(KioskAppManager* manager, + const std::string& app_id, + const std::string& version) + : runner_(NULL), + manager_(manager), + wait_type_(WAIT_FOR_CRX_CACHE), + loaded_(false), + quit_(false), + app_id_(app_id), + version_(version) { + manager_->AddObserver(this); + } + + ~AppDataLoadWaiter() override { manager_->RemoveObserver(this); } + + void Wait() { + wait_type_ = WAIT_FOR_CRX_CACHE; + if (quit_) + return; + runner_ = new content::MessageLoopRunner; + runner_->Run(); + } + + void WaitForAppData() { + wait_type_ = WAIT_FOR_APP_DATA; + if (quit_ || IsAppDataLoaded()) + return; + runner_ = new content::MessageLoopRunner; + runner_->Run(); + } + + bool loaded() const { return loaded_; } + + private: + enum WaitType { + WAIT_FOR_CRX_CACHE, + WAIT_FOR_APP_DATA, + }; + + // KioskAppManagerObserver overrides: + void OnKioskAppDataChanged(const std::string& app_id) override { + if (wait_type_ != WAIT_FOR_APP_DATA || + app_id != app_id_ || + !IsAppDataLoaded()) { + return; + } + + loaded_ = true; + quit_ = true; + if (runner_.get()) + runner_->Quit(); + } + + void OnKioskAppDataLoadFailure(const std::string& app_id) override { + if (wait_type_ != WAIT_FOR_APP_DATA || app_id != app_id_) + return; + + loaded_ = false; + quit_ = true; + if (runner_.get()) + runner_->Quit(); + } + + void OnKioskExtensionLoadedInCache(const std::string& app_id) override { + if (wait_type_ != WAIT_FOR_CRX_CACHE) + return; + + std::string cached_version; + base::FilePath file_path; + if (!manager_->GetCachedCrx(app_id_, &file_path, &cached_version)) + return; + if (version_ != cached_version) + return; + loaded_ = true; + quit_ = true; + if (runner_.get()) + runner_->Quit(); + } + + void OnKioskExtensionDownloadFailed(const std::string& app_id) override { + if (wait_type_ != WAIT_FOR_CRX_CACHE) + return; + + loaded_ = false; + quit_ = true; + if (runner_.get()) + runner_->Quit(); + } + + bool IsAppDataLoaded() { + KioskAppManager::App app; + return manager_->GetApp(app_id_, &app) && !app.is_loading; + } + + scoped_refptr<content::MessageLoopRunner> runner_; + KioskAppManager* manager_; + WaitType wait_type_; + bool loaded_; + bool quit_; + std::string app_id_; + std::string version_; + + DISALLOW_COPY_AND_ASSIGN(AppDataLoadWaiter); +}; + } // namespace class KioskTest : public OobeBaseTest { @@ -1212,63 +1319,6 @@ DISALLOW_COPY_AND_ASSIGN(KioskAppExternalUpdateWaiter); }; - class AppDataLoadWaiter : public KioskAppManagerObserver { - public: - AppDataLoadWaiter(KioskAppManager* manager, - const std::string& app_id, - const std::string& version) - : runner_(NULL), - manager_(manager), - loaded_(false), - quit_(false), - app_id_(app_id), - version_(version) { - manager_->AddObserver(this); - } - - ~AppDataLoadWaiter() override { manager_->RemoveObserver(this); } - - void Wait() { - if (quit_) - return; - runner_ = new content::MessageLoopRunner; - runner_->Run(); - } - - bool loaded() const { return loaded_; } - - private: - // KioskAppManagerObserver overrides: - void OnKioskExtensionLoadedInCache(const std::string& app_id) override { - std::string cached_version; - base::FilePath file_path; - if (!manager_->GetCachedCrx(app_id_, &file_path, &cached_version)) - return; - if (version_ != cached_version) - return; - loaded_ = true; - quit_ = true; - if (runner_.get()) - runner_->Quit(); - } - - void OnKioskExtensionDownloadFailed(const std::string& app_id) override { - loaded_ = false; - quit_ = true; - if (runner_.get()) - runner_->Quit(); - } - - scoped_refptr<content::MessageLoopRunner> runner_; - KioskAppManager* manager_; - bool loaded_; - bool quit_; - std::string app_id_; - std::string version_; - - DISALLOW_COPY_AND_ASSIGN(AppDataLoadWaiter); - }; - // Owned by DiskMountManager. KioskFakeDiskMountManager* fake_disk_mount_manager_; @@ -1751,6 +1801,11 @@ kTestEnterpriseKioskApp, private_server.GetURL(kPrivateStoreUpdate).spec()); + // Meta should be able to be extracted from crx before launching. + KioskAppManager* manager = KioskAppManager::Get(); + AppDataLoadWaiter waiter(manager, kTestEnterpriseKioskApp, std::string()); + waiter.WaitForAppData(); + PrepareAppLaunch(); LaunchApp(kTestEnterpriseKioskApp, false); WaitForAppLaunchWithOptions(false /* check_launch_data */,
diff --git a/chrome/browser/chromeos/login/lock/screen_locker_browsertest.cc b/chrome/browser/chromeos/login/lock/screen_locker_browsertest.cc index d5558b8..8de336e 100644 --- a/chrome/browser/chromeos/login/lock/screen_locker_browsertest.cc +++ b/chrome/browser/chromeos/login/lock/screen_locker_browsertest.cc
@@ -185,7 +185,10 @@ browser_window->GetNativeWindow()); { Waiter waiter(browser()); - browser()->fullscreen_controller()->ToggleBrowserFullscreenMode(); + browser() + ->exclusive_access_manager() + ->fullscreen_controller() + ->ToggleBrowserFullscreenMode(); waiter.Wait(false /* not locked */, true /* full screen */); EXPECT_TRUE(browser_window->IsFullscreen()); EXPECT_FALSE(window_state->hide_shelf_when_fullscreen()); @@ -208,7 +211,10 @@ EXPECT_FALSE(tester->IsLocked()); { Waiter waiter(browser()); - browser()->fullscreen_controller()->ToggleBrowserFullscreenMode(); + browser() + ->exclusive_access_manager() + ->fullscreen_controller() + ->ToggleBrowserFullscreenMode(); waiter.Wait(false /* not locked */, false /* fullscreen */); EXPECT_FALSE(browser_window->IsFullscreen()); } @@ -220,8 +226,10 @@ Waiter waiter(browser()); content::WebContents* web_contents = browser()->tab_strip_model()->GetActiveWebContents(); - browser()->fullscreen_controller()->EnterFullscreenModeForTab( - web_contents, GURL()); + browser() + ->exclusive_access_manager() + ->fullscreen_controller() + ->EnterFullscreenModeForTab(web_contents, GURL()); waiter.Wait(false /* not locked */, true /* fullscreen */); EXPECT_TRUE(browser_window->IsFullscreen()); EXPECT_TRUE(window_state->hide_shelf_when_fullscreen());
diff --git a/chrome/browser/chromeos/login/proxy_auth_dialog_browsertest.cc b/chrome/browser/chromeos/login/proxy_auth_dialog_browsertest.cc new file mode 100644 index 0000000..eca6b5c4 --- /dev/null +++ b/chrome/browser/chromeos/login/proxy_auth_dialog_browsertest.cc
@@ -0,0 +1,123 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/command_line.h" +#include "base/files/file_path.h" +#include "base/macros.h" +#include "base/run_loop.h" +#include "chrome/browser/chrome_notification_types.h" +#include "chrome/browser/chromeos/login/login_manager_test.h" +#include "chrome/browser/chromeos/login/startup_utils.h" +#include "chrome/browser/chromeos/login/test/oobe_screen_waiter.h" +#include "chrome/browser/chromeos/login/ui/login_display_host_impl.h" +#include "chrome/browser/chromeos/login/ui/login_display_host_impl.h" +#include "chrome/browser/chromeos/login/ui/webui_login_view.h" +#include "chrome/browser/ui/login/login_prompt.h" +#include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/common/chrome_switches.h" +#include "content/public/browser/notification_details.h" +#include "content/public/browser/web_ui.h" +#include "content/public/browser/web_ui_controller.h" +#include "content/public/test/browser_test_utils.h" +#include "content/public/test/test_utils.h" +#include "net/test/spawned_test_server/spawned_test_server.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace chromeos { + +namespace { + +class ProxyAuthDialogWaiter : public content::WindowedNotificationObserver { + public: + ProxyAuthDialogWaiter() + : WindowedNotificationObserver( + chrome::NOTIFICATION_AUTH_NEEDED, + base::Bind(&ProxyAuthDialogWaiter::SetLoginHandler, + base::Unretained(this))), + login_handler_(nullptr) {} + + ~ProxyAuthDialogWaiter() override {} + + LoginHandler* login_handler() const { return login_handler_; } + + private: + bool SetLoginHandler(const content::NotificationSource& /* source */, + const content::NotificationDetails& details) { + login_handler_ = + content::Details<LoginNotificationDetails>(details)->handler(); + return true; + } + + LoginHandler* login_handler_; + + DISALLOW_COPY_AND_ASSIGN(ProxyAuthDialogWaiter); +}; + +} // namespace + +class ProxyAuthOnUserBoardScreenTest : public LoginManagerTest { + public: + ProxyAuthOnUserBoardScreenTest() + : LoginManagerTest(true /* should_launch_browser */), + proxy_server_(net::SpawnedTestServer::TYPE_BASIC_AUTH_PROXY, + net::SpawnedTestServer::kLocalhost, + base::FilePath()) {} + + ~ProxyAuthOnUserBoardScreenTest() override {} + + void SetUp() override { + ASSERT_TRUE(proxy_server_.Start()); + LoginManagerTest::SetUp(); + } + + void SetUpCommandLine(base::CommandLine* command_line) override { + LoginManagerTest::SetUpCommandLine(command_line); + command_line->AppendSwitchASCII(::switches::kProxyServer, + proxy_server_.host_port_pair().ToString()); + } + + private: + net::SpawnedTestServer proxy_server_; + + DISALLOW_COPY_AND_ASSIGN(ProxyAuthOnUserBoardScreenTest); +}; + +IN_PROC_BROWSER_TEST_F(ProxyAuthOnUserBoardScreenTest, + PRE_ProxyAuthDialogOnUserBoardScreen) { + RegisterUser("test-user@gmail.com"); + StartupUtils::MarkOobeCompleted(); +} + +IN_PROC_BROWSER_TEST_F(ProxyAuthOnUserBoardScreenTest, + ProxyAuthDialogOnUserBoardScreen) { + LoginDisplayHost* login_display_host = LoginDisplayHostImpl::default_host(); + WebUILoginView* web_ui_login_view = login_display_host->GetWebUILoginView(); + OobeUI* oobe_ui = + static_cast<OobeUI*>(web_ui_login_view->GetWebUI()->GetController()); + + { + OobeScreenWaiter screen_waiter(OobeDisplay::SCREEN_ACCOUNT_PICKER); + ProxyAuthDialogWaiter auth_dialog_waiter; + screen_waiter.Wait(); + auth_dialog_waiter.Wait(); + + ASSERT_TRUE(auth_dialog_waiter.login_handler()); + auth_dialog_waiter.login_handler()->CancelAuth(); + } + + { + OobeScreenWaiter screen_waiter(OobeDisplay::SCREEN_GAIA_SIGNIN); + ProxyAuthDialogWaiter auth_dialog_waiter; + ASSERT_TRUE(content::ExecuteScript(oobe_ui->web_ui()->GetWebContents(), + "window.domAutomationController.send(!!(" + "$('add-user-button').click()" + "));")); + screen_waiter.Wait(); + auth_dialog_waiter.Wait(); + ASSERT_TRUE(auth_dialog_waiter.login_handler()); + } +} + +} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/screens/user_selection_screen.cc b/chrome/browser/chromeos/login/screens/user_selection_screen.cc index 16cac17..095359ec 100644 --- a/chrome/browser/chromeos/login/screens/user_selection_screen.cc +++ b/chrome/browser/chromeos/login/screens/user_selection_screen.cc
@@ -36,6 +36,7 @@ const char kKeyEnterpriseDomain[] = "enterpriseDomain"; const char kKeyPublicAccount[] = "publicAccount"; const char kKeySupervisedUser[] = "supervisedUser"; +const char kKeyChildUser[] = "childUser"; const char kKeySignedIn[] = "signedIn"; const char kKeyCanRemove[] = "canRemove"; const char kKeyIsOwner[] = "isOwner"; @@ -141,12 +142,14 @@ user->GetType() == user_manager::USER_TYPE_PUBLIC_ACCOUNT; const bool is_supervised_user = user->GetType() == user_manager::USER_TYPE_SUPERVISED; + const bool is_child_user = user->GetType() == user_manager::USER_TYPE_CHILD; user_dict->SetString(kKeyUsername, user_id); user_dict->SetString(kKeyEmailAddress, user->display_email()); user_dict->SetString(kKeyDisplayName, user->GetDisplayName()); user_dict->SetBoolean(kKeyPublicAccount, is_public_session); user_dict->SetBoolean(kKeySupervisedUser, is_supervised_user); + user_dict->SetBoolean(kKeyChildUser, is_child_user); user_dict->SetInteger(kKeyInitialAuthType, auth_type); user_dict->SetBoolean(kKeySignedIn, user->is_logged_in()); user_dict->SetBoolean(kKeyIsOwner, is_owner);
diff --git a/chrome/browser/chromeos/net/network_portal_detector_impl.cc b/chrome/browser/chromeos/net/network_portal_detector_impl.cc index 7a81f013..3dbe501 100644 --- a/chrome/browser/chromeos/net/network_portal_detector_impl.cc +++ b/chrome/browser/chromeos/net/network_portal_detector_impl.cc
@@ -15,8 +15,8 @@ #include "chrome/browser/chrome_notification_types.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/shill_profile_client.h" +#include "chromeos/device_event_log.h" #include "chromeos/login/login_state.h" -#include "chromeos/network/network_event_log.h" #include "chromeos/network/network_state.h" #include "chromeos/network/network_state_handler.h" #include "content/public/browser/notification_service.h" @@ -162,21 +162,13 @@ void NetworkPortalDetectorImpl::DetectionAttemptCompletedReport::Report() const { - // TODO (ygorshenin@): remove VLOG as soon as NET_LOG_EVENT will be dumped on - // a disk, crbug.com/293739. - VLOG(1) << "Detection attempt completed: " - << "name=" << network_name << ", " - << "id=" << network_id << ", " - << "result=" << captive_portal::CaptivePortalResultToString(result) - << ", " - << "response_code=" << response_code; - NET_LOG_EVENT(StringPrintf( - "Portal detection completed: network_id=%s, result=%s, " - "response_code=%d", - network_id.c_str(), - captive_portal::CaptivePortalResultToString(result).c_str(), - response_code), - network_name); + // To see NET_LOG output, use '--vmodule=device_event_log*=1' + NET_LOG(EVENT) << "Detection attempt completed: " + << "name=" << network_name << ", " + << "id=" << network_id << ", " + << "result=" + << captive_portal::CaptivePortalResultToString(result) << ", " + << "response_code=" << response_code; } bool NetworkPortalDetectorImpl::DetectionAttemptCompletedReport::Equals( @@ -221,6 +213,7 @@ return; CHECK(!NetworkPortalDetector::network_portal_detector()) << "NetworkPortalDetector was initialized twice."; + NET_LOG(EVENT) << "NetworkPortalDetectorImpl::Initialize()"; if (base::CommandLine::ForCurrentProcess()->HasSwitch(::switches::kTestType)) set_network_portal_detector(new NetworkPortalDetectorStubImpl()); else @@ -238,6 +231,7 @@ same_detection_result_count_(0), no_response_result_count_(0), weak_factory_(this) { + NET_LOG(EVENT) << "NetworkPortalDetectorImpl::NetworkPortalDetectorImpl()"; captive_portal_detector_.reset(new CaptivePortalDetector(request_context)); registrar_.Add(this, @@ -255,6 +249,7 @@ } NetworkPortalDetectorImpl::~NetworkPortalDetectorImpl() { + NET_LOG(EVENT) << "NetworkPortalDetectorImpl::~NetworkPortalDetectorImpl()"; DCHECK(CalledOnValidThread()); attempt_task_.Cancel(); @@ -306,9 +301,8 @@ const NetworkState* network = DefaultNetwork(); if (!start_detection || !network) return; - NET_LOG_EVENT(StringPrintf("Starting detection attempt: network_id=%s", - network->guid().c_str()), - network->name()); + NET_LOG(EVENT) << "Starting detection attempt:" + << " name=" << network->name() << " id=" << network->guid(); portal_state_map_.erase(network->guid()); StartDetection(); } @@ -343,7 +337,7 @@ DCHECK(CalledOnValidThread()); if (!default_network) { - NET_LOG_EVENT("Default network changed", "None"); + NET_LOG(EVENT) << "Default network changed: None"; default_network_name_.clear(); @@ -364,14 +358,12 @@ (default_connection_state_ != default_network->connection_state()); default_connection_state_ = default_network->connection_state(); - NET_LOG_EVENT(StringPrintf( - "Default network changed: network_id=%s, state=%s, " - "changed=%d, state_changed=%d", - default_network_id_.c_str(), - default_connection_state_.c_str(), - network_changed, - connection_state_changed), - default_network_name_); + NET_LOG(EVENT) << "Default network changed:" + << " name=" << default_network_name_ + << " id=" << default_network_id_ + << " state=" << default_connection_state_ + << " changed=" << network_changed + << " state_changed=" << connection_state_changed; if (network_changed || connection_state_changed) StopDetection(); @@ -464,9 +456,9 @@ DCHECK(CalledOnValidThread()); DCHECK(is_checking_for_portal()); - NET_LOG_ERROR(StringPrintf("Portal detection timeout: network_id=%s", - default_network_id_.c_str()), - default_network_name_); + NET_LOG(ERROR) << "Portal detection timeout: " + << " name=" << default_network_name_ + << " id=" << default_network_id_; captive_portal_detector_->Cancel(); CaptivePortalDetector::Results results; @@ -564,9 +556,8 @@ if (type == chrome::NOTIFICATION_LOGIN_PROXY_CHANGED || type == chrome::NOTIFICATION_AUTH_SUPPLIED || type == chrome::NOTIFICATION_AUTH_CANCELLED) { - NET_LOG_EVENT( - "Restarting portal detection due to proxy change", - default_network_name_.empty() ? "None" : default_network_name_); + NET_LOG(EVENT) << "Restarting portal detection due to proxy change" + << " name=" << default_network_name_; StopDetection(); ScheduleAttempt(base::TimeDelta::FromSeconds(kProxyChangeDelaySec)); }
diff --git a/chrome/browser/chromeos/offline/offline_load_page.cc b/chrome/browser/chromeos/offline/offline_load_page.cc index e50c0fc..d9a5fa24 100644 --- a/chrome/browser/chromeos/offline/offline_load_page.cc +++ b/chrome/browser/chromeos/offline/offline_load_page.cc
@@ -94,9 +94,10 @@ resource_id = IDR_OFFLINE_NET_LOAD_HTML; } - const base::StringPiece template_html( - ResourceBundle::GetSharedInstance().GetRawDataResource( - resource_id)); + std::string template_html = ResourceBundle::GetSharedInstance() + .GetRawDataResource(resource_id) + .as_string(); + webui::AppendWebUiCssTextDefaults(&template_html); // "t" is the id of the templates root node. return webui::GetTemplatesHtml(template_html, &error_strings, "t"); }
diff --git a/chrome/browser/chromeos/options/vpn_config_view.cc b/chrome/browser/chromeos/options/vpn_config_view.cc index 6cda28c..024bbaf 100644 --- a/chrome/browser/chromeos/options/vpn_config_view.cc +++ b/chrome/browser/chromeos/options/vpn_config_view.cc
@@ -1000,7 +1000,7 @@ const NetworkState* vpn = NetworkHandler::Get()->network_state_handler()-> GetNetworkState(service_path_); if (vpn && vpn->connection_state() == shill::kStateFailure) - error_msg = ui::NetworkConnect::Get()->GetErrorString( + error_msg = ui::NetworkConnect::Get()->GetShillErrorString( vpn->last_error(), vpn->path()); } if (!error_msg.empty()) {
diff --git a/chrome/browser/chromeos/options/wifi_config_view.cc b/chrome/browser/chromeos/options/wifi_config_view.cc index 70a76bc9..ffa932e 100644 --- a/chrome/browser/chromeos/options/wifi_config_view.cc +++ b/chrome/browser/chromeos/options/wifi_config_view.cc
@@ -588,7 +588,7 @@ if (error_msg.empty() && !service_path_.empty()) { const NetworkState* network = GetNetworkState(); if (network && network->connection_state() == shill::kStateFailure) { - error_msg = ui::NetworkConnect::Get()->GetErrorString( + error_msg = ui::NetworkConnect::Get()->GetShillErrorString( network->last_error(), network->path()); } }
diff --git a/chrome/browser/chromeos/options/wimax_config_view.cc b/chrome/browser/chromeos/options/wimax_config_view.cc index c3cf96bf..ed39f49f 100644 --- a/chrome/browser/chromeos/options/wimax_config_view.cc +++ b/chrome/browser/chromeos/options/wimax_config_view.cc
@@ -100,7 +100,7 @@ const NetworkState* wimax = NetworkHandler::Get()->network_state_handler()-> GetNetworkState(service_path_); if (wimax && wimax->connection_state() == shill::kStateFailure) - error_msg = ui::NetworkConnect::Get()->GetErrorString( + error_msg = ui::NetworkConnect::Get()->GetShillErrorString( wimax->last_error(), wimax->path()); } if (!error_msg.empty()) {
diff --git a/chrome/browser/chromeos/policy/consumer_management_notifier.cc b/chrome/browser/chromeos/policy/consumer_management_notifier.cc index 3c42733..8cba0ed 100644 --- a/chrome/browser/chromeos/policy/consumer_management_notifier.cc +++ b/chrome/browser/chromeos/policy/consumer_management_notifier.cc
@@ -171,7 +171,6 @@ l10n_util::GetStringUTF16(body_message_id), ui::ResourceBundle::GetSharedInstance().GetImageNamed( IDR_CONSUMER_MANAGEMENT_NOTIFICATION_ICON), - blink::WebTextDirectionDefault, message_center::NotifierId(message_center::NotifierId::SYSTEM_COMPONENT, notification_id), base::string16(), // display_source
diff --git a/chrome/browser/chromeos/policy/device_status_collector.cc b/chrome/browser/chromeos/policy/device_status_collector.cc index 9378b58b..82134f4 100644 --- a/chrome/browser/chromeos/policy/device_status_collector.cc +++ b/chrome/browser/chromeos/policy/device_status_collector.cc
@@ -489,10 +489,10 @@ em::DeviceStatusReportRequest* request) { std::string dev_switch_mode; if (statistics_provider_->GetMachineStatistic( - chromeos::system::kDevSwitchBootMode, &dev_switch_mode)) { - if (dev_switch_mode == "1") + chromeos::system::kDevSwitchBootKey, &dev_switch_mode)) { + if (dev_switch_mode == chromeos::system::kDevSwitchBootValueDev) request->set_boot_mode("Dev"); - else if (dev_switch_mode == "0") + else if (dev_switch_mode == chromeos::system::kDevSwitchBootValueVerified) request->set_boot_mode("Verified"); } }
diff --git a/chrome/browser/chromeos/policy/device_status_collector_browsertest.cc b/chrome/browser/chromeos/policy/device_status_collector_browsertest.cc index 178c3ba..38e3478 100644 --- a/chrome/browser/chromeos/policy/device_status_collector_browsertest.cc +++ b/chrome/browser/chromeos/policy/device_status_collector_browsertest.cc
@@ -593,7 +593,9 @@ TEST_F(DeviceStatusCollectorTest, DevSwitchBootMode) { // Test that boot mode data is reported by default. - fake_statistics_provider_.SetMachineStatistic("devsw_boot", "0"); + fake_statistics_provider_.SetMachineStatistic( + chromeos::system::kDevSwitchBootKey, + chromeos::system::kDevSwitchBootValueVerified); GetStatus(); EXPECT_EQ("Verified", status_.boot_mode()); @@ -607,19 +609,25 @@ // statistics provider returns valid data. cros_settings_->SetBoolean(chromeos::kReportDeviceBootMode, true); - fake_statistics_provider_.SetMachineStatistic("devsw_boot", "(error)"); + fake_statistics_provider_.SetMachineStatistic( + chromeos::system::kDevSwitchBootKey, "(error)"); GetStatus(); EXPECT_FALSE(status_.has_boot_mode()); - fake_statistics_provider_.SetMachineStatistic("devsw_boot", " "); + fake_statistics_provider_.SetMachineStatistic( + chromeos::system::kDevSwitchBootKey, " "); GetStatus(); EXPECT_FALSE(status_.has_boot_mode()); - fake_statistics_provider_.SetMachineStatistic("devsw_boot", "0"); + fake_statistics_provider_.SetMachineStatistic( + chromeos::system::kDevSwitchBootKey, + chromeos::system::kDevSwitchBootValueVerified); GetStatus(); EXPECT_EQ("Verified", status_.boot_mode()); - fake_statistics_provider_.SetMachineStatistic("devsw_boot", "1"); + fake_statistics_provider_.SetMachineStatistic( + chromeos::system::kDevSwitchBootKey, + chromeos::system::kDevSwitchBootValueDev); GetStatus(); EXPECT_EQ("Dev", status_.boot_mode()); }
diff --git a/chrome/browser/chromeos/policy/device_system_use_24hour_clock_browsertest.cc b/chrome/browser/chromeos/policy/device_system_use_24hour_clock_browsertest.cc index 8c770da..8ff431db 100644 --- a/chrome/browser/chromeos/policy/device_system_use_24hour_clock_browsertest.cc +++ b/chrome/browser/chromeos/policy/device_system_use_24hour_clock_browsertest.cc
@@ -8,11 +8,14 @@ #include "ash/system/user/login_status.h" #include "base/command_line.h" #include "base/message_loop/message_loop.h" +#include "chrome/browser/chromeos/login/ui/login_display_host_impl.h" #include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h" #include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h" #include "chrome/browser/chromeos/settings/cros_settings.h" +#include "chrome/browser/lifetime/application_lifetime.h" #include "chrome/browser/ui/ash/system_tray_delegate_chromeos.h" #include "chromeos/chromeos_switches.h" +#include "content/public/test/test_utils.h" #include "testing/gtest/include/gtest/gtest.h" namespace em = enterprise_management; @@ -36,6 +39,15 @@ DevicePolicyCrosBrowserTest::SetUpInProcessBrowserTestFixture(); } + void TearDownOnMainThread() override { + // If the login display is still showing, exit gracefully. + if (LoginDisplayHostImpl::default_host()) { + base::MessageLoop::current()->PostTask(FROM_HERE, + base::Bind(&chrome::AttemptExit)); + content::RunMessageLoop(); + } + } + protected: void RefreshPolicyAndWaitDeviceSettingsUpdated() { scoped_ptr<CrosSettings::ObserverSubscription> observer = @@ -94,7 +106,7 @@ }; // Disabled due to flakiness - http://crbug.com/450651. -IN_PROC_BROWSER_TEST_F(SystemUse24HourClockPolicyTest, DISABLED_CheckUnset) { +IN_PROC_BROWSER_TEST_F(SystemUse24HourClockPolicyTest, CheckUnset) { bool system_use_24hour_clock; EXPECT_FALSE(CrosSettings::Get()->GetBoolean(kSystemUse24HourClock, &system_use_24hour_clock)); @@ -108,7 +120,7 @@ } // Disabled due to flakiness - http://crbug.com/450651. -IN_PROC_BROWSER_TEST_F(SystemUse24HourClockPolicyTest, DISABLED_CheckTrue) { +IN_PROC_BROWSER_TEST_F(SystemUse24HourClockPolicyTest, CheckTrue) { bool system_use_24hour_clock = true; EXPECT_FALSE(CrosSettings::Get()->GetBoolean(kSystemUse24HourClock, &system_use_24hour_clock)); @@ -135,7 +147,7 @@ } // Disabled due to flakiness - http://crbug.com/450651. -IN_PROC_BROWSER_TEST_F(SystemUse24HourClockPolicyTest, DISABLED_CheckFalse) { +IN_PROC_BROWSER_TEST_F(SystemUse24HourClockPolicyTest, CheckFalse) { bool system_use_24hour_clock = true; EXPECT_FALSE(CrosSettings::Get()->GetBoolean(kSystemUse24HourClock, &system_use_24hour_clock));
diff --git a/chrome/browser/chromeos/power/peripheral_battery_observer.cc b/chrome/browser/chromeos/power/peripheral_battery_observer.cc index 42be633..cebc514d 100644 --- a/chrome/browser/chromeos/power/peripheral_battery_observer.cc +++ b/chrome/browser/chromeos/power/peripheral_battery_observer.cc
@@ -214,7 +214,6 @@ string_text, ui::ResourceBundle::GetSharedInstance().GetImageNamed( IDR_NOTIFICATION_PERIPHERAL_BATTERY_LOW), - blink::WebTextDirectionDefault, message_center::NotifierId(GURL(kNotificationOriginUrl)), base::string16(), base::UTF8ToUTF16(address),
diff --git a/chrome/browser/chromeos/settings/shutdown_policy_handler.cc b/chrome/browser/chromeos/settings/shutdown_policy_handler.cc index cc1a322..095a9868 100644 --- a/chrome/browser/chromeos/settings/shutdown_policy_handler.cc +++ b/chrome/browser/chromeos/settings/shutdown_policy_handler.cc
@@ -22,8 +22,7 @@ } } -ShutdownPolicyHandler::~ShutdownPolicyHandler() { -} +ShutdownPolicyHandler::~ShutdownPolicyHandler() {} void ShutdownPolicyHandler::Shutdown() { shutdown_policy_subscription_.reset();
diff --git a/chrome/browser/chromeos/settings/shutdown_policy_handler_unittest.cc b/chrome/browser/chromeos/settings/shutdown_policy_handler_unittest.cc index 2dabe53..eadd410 100644 --- a/chrome/browser/chromeos/settings/shutdown_policy_handler_unittest.cc +++ b/chrome/browser/chromeos/settings/shutdown_policy_handler_unittest.cc
@@ -111,7 +111,7 @@ base::Unretained(this))); base::RunLoop().RunUntilIdle(); EXPECT_TRUE(callback_called_); - EXPECT_EQ(true, reboot_on_shutdown_); + EXPECT_TRUE(reboot_on_shutdown_); // Forbid shutdown. SetRebootOnShutdown(false); callback_called_ = false; @@ -120,7 +120,7 @@ base::Unretained(this))); base::RunLoop().RunUntilIdle(); EXPECT_TRUE(callback_called_); - EXPECT_EQ(false, reboot_on_shutdown_); + EXPECT_FALSE(reboot_on_shutdown_); } } // namespace chromeos
diff --git a/chrome/browser/chromeos/shutdown_policy_browsertest.cc b/chrome/browser/chromeos/shutdown_policy_browsertest.cc new file mode 100644 index 0000000..fea5b14 --- /dev/null +++ b/chrome/browser/chromeos/shutdown_policy_browsertest.cc
@@ -0,0 +1,338 @@ +// Copyright 2015 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 <string> + +#include "ash/shell.h" +#include "ash/strings/grit/ash_strings.h" +#include "ash/system/date/date_default_view.h" +#include "ash/system/date/tray_date.h" +#include "ash/system/tray/system_tray.h" +#include "ash/system/tray/tray_popup_header_button.h" +#include "ash/system/user/login_status.h" +#include "base/command_line.h" +#include "base/location.h" +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "base/message_loop/message_loop.h" +#include "base/run_loop.h" +#include "base/strings/stringprintf.h" +#include "chrome/browser/chrome_notification_types.h" +#include "chrome/browser/chromeos/login/lock/screen_locker.h" +#include "chrome/browser/chromeos/login/lock/screen_locker_tester.h" +#include "chrome/browser/chromeos/login/lock/webui_screen_locker.h" +#include "chrome/browser/chromeos/login/ui/login_display_host_impl.h" +#include "chrome/browser/chromeos/login/ui/webui_login_view.h" +#include "chrome/browser/chromeos/policy/device_policy_builder.h" +#include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h" +#include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h" +#include "chrome/browser/chromeos/settings/device_settings_service.h" +#include "chrome/browser/lifetime/application_lifetime.h" +#include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h" +#include "chromeos/chromeos_switches.h" +#include "chromeos/dbus/dbus_thread_manager.h" +#include "chromeos/dbus/fake_session_manager_client.h" +#include "chromeos/dbus/session_manager_client.h" +#include "content/public/browser/notification_service.h" +#include "content/public/browser/web_contents.h" +#include "content/public/browser/web_ui.h" +#include "content/public/test/browser_test_utils.h" +#include "content/public/test/test_utils.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/compositor/scoped_animation_duration_scale_mode.h" +#include "ui/views/view.h" + +namespace em = enterprise_management; + +namespace chromeos { + +namespace { + +const char kWaitForHiddenStateScript[] = + "var screenElement = document.getElementById('%s');" + "var expectation = %s;" + "function SendReplyIfAsExpected() {" + " if (screenElement.hidden != expectation)" + " return false;" + " domAutomationController.send(screenElement.hidden);" + " observer.disconnect();" + " return true;" + "}" + "var observer = new MutationObserver(SendReplyIfAsExpected);" + "if (!SendReplyIfAsExpected()) {" + " var options = { attributes: true };" + " observer.observe(screenElement, options);" + "}"; + +} // namespace + +class ShutdownPolicyBaseTest + : public policy::DevicePolicyCrosBrowserTest, + public DeviceSettingsService::Observer { + protected: + ShutdownPolicyBaseTest() : contents_(nullptr) {} + ~ShutdownPolicyBaseTest() override {} + + // DeviceSettingsService::Observer: + void OwnershipStatusChanged() override {} + void DeviceSettingsUpdated() override { + if (run_loop_) + run_loop_->Quit(); + } + void OnDeviceSettingsServiceShutdown() override {} + + // policy::DevicePolicyCrosBrowserTest: + void SetUpInProcessBrowserTestFixture() override { + policy::DevicePolicyCrosBrowserTest::SetUpInProcessBrowserTestFixture(); + InstallOwnerKey(); + MarkAsEnterpriseOwned(); + } + + // A helper functions which prepares the script by injecting the element_id of + // the element whose hiddenness we want to check and the expectation. + std::string PrepareScript(const std::string& element_id, bool expectation) { + return base::StringPrintf(kWaitForHiddenStateScript, element_id.c_str(), + expectation ? "true" : "false"); + } + + // Checks whether the element identified by |element_id| is hidden and only + // returns if the expectation is fulfilled. + void PrepareAndRunScript(const std::string& element_id, bool expectation) { + ASSERT_TRUE(content::ExecuteScriptAndExtractBool( + contents_, PrepareScript(element_id, expectation), + &result_)); + } + + // Updates the device shutdown policy and sets it to |reboot_on_shutdown|. + void UpdateRebootOnShutdownPolicy(bool reboot_on_shutdown) { + policy::DevicePolicyBuilder* builder = device_policy(); + ASSERT_TRUE(builder); + em::ChromeDeviceSettingsProto& proto(builder->payload()); + proto.mutable_reboot_on_shutdown()->set_reboot_on_shutdown( + reboot_on_shutdown); + } + + // Refreshes device policy and waits for it to be applied. + void SyncRefreshDevicePolicy() { + run_loop_.reset(new base::RunLoop()); + DeviceSettingsService::Get()->AddObserver(this); + RefreshDevicePolicy(); + run_loop_->Run(); + DeviceSettingsService::Get()->RemoveObserver(this); + run_loop_.reset(); + } + + // Blocks until the OobeUI indicates that the javascript side has been + // initialized. + void WaitUntilOobeUIIsReady(OobeUI* oobe_ui) { + ASSERT_TRUE(oobe_ui); + base::RunLoop run_loop; + const bool oobe_ui_ready = oobe_ui->IsJSReady(run_loop.QuitClosure()); + if (!oobe_ui_ready) + run_loop.Run(); + } + + content::WebContents* contents_; + bool result_; + scoped_ptr<base::RunLoop> run_loop_; +}; + +class ShutdownPolicyInSessionTest + : public ShutdownPolicyBaseTest { + protected: + ShutdownPolicyInSessionTest() {} + ~ShutdownPolicyInSessionTest() override {} + + void SetUpOnMainThread() override { + ShutdownPolicyBaseTest::SetUpOnMainThread(); + ash::TrayDate* tray_date = ash::Shell::GetInstance() + ->GetPrimarySystemTray() + ->GetTrayDateForTesting(); + ASSERT_TRUE(tray_date); + date_default_view_.reset( + static_cast<ash::DateDefaultView*>( + tray_date->CreateDefaultViewForTesting(ash::user::LOGGED_IN_USER))); + ASSERT_TRUE(date_default_view_); + } + + void TearDownOnMainThread() override { + date_default_view_.reset(); + ShutdownPolicyBaseTest::TearDownOnMainThread(); + } + + // Get the shutdown and reboot button view from the date default view. + const ash::TrayPopupHeaderButton* GetShutdownButton() { + return static_cast<const ash::TrayPopupHeaderButton*>( + date_default_view_->GetShutdownButtonViewForTest()); + } + + bool HasButtonTooltipText(const ash::TrayPopupHeaderButton* button, + int message_id) const { + base::string16 actual_tooltip; + button->GetTooltipText(gfx::Point(), &actual_tooltip); + return l10n_util::GetStringUTF16(message_id) == actual_tooltip; + } + + private: + scoped_ptr<ash::DateDefaultView> date_default_view_; + + DISALLOW_COPY_AND_ASSIGN(ShutdownPolicyInSessionTest); +}; + +IN_PROC_BROWSER_TEST_F(ShutdownPolicyInSessionTest, TestBasic) { + const ash::TrayPopupHeaderButton *shutdown_button = GetShutdownButton(); + EXPECT_TRUE( + HasButtonTooltipText(shutdown_button, IDS_ASH_STATUS_TRAY_SHUTDOWN)); +} + +IN_PROC_BROWSER_TEST_F(ShutdownPolicyInSessionTest, PolicyChange) { + const ash::TrayPopupHeaderButton *shutdown_button = GetShutdownButton(); + + UpdateRebootOnShutdownPolicy(true); + SyncRefreshDevicePolicy(); + EXPECT_TRUE( + HasButtonTooltipText(shutdown_button, IDS_ASH_STATUS_TRAY_REBOOT)); + + UpdateRebootOnShutdownPolicy(false); + SyncRefreshDevicePolicy(); + EXPECT_TRUE( + HasButtonTooltipText(shutdown_button, IDS_ASH_STATUS_TRAY_SHUTDOWN)); +} + +class ShutdownPolicyLockerTest : public ShutdownPolicyBaseTest { + protected: + ShutdownPolicyLockerTest() : fake_session_manager_client_(nullptr) {} + ~ShutdownPolicyLockerTest() override {} + + void SetUpInProcessBrowserTestFixture() override { + fake_session_manager_client_ = new FakeSessionManagerClient; + DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient( + scoped_ptr<SessionManagerClient>(fake_session_manager_client_)); + + ShutdownPolicyBaseTest::SetUpInProcessBrowserTestFixture(); + zero_duration_mode_.reset(new ui::ScopedAnimationDurationScaleMode( + ui::ScopedAnimationDurationScaleMode::ZERO_DURATION)); + InstallOwnerKey(); + MarkAsEnterpriseOwned(); + } + + void SetUpOnMainThread() override { + ShutdownPolicyBaseTest::SetUpOnMainThread(); + + // Bring up the locker screen. + ScreenLocker::Show(); + scoped_ptr<test::ScreenLockerTester> tester(ScreenLocker::GetTester()); + tester->EmulateWindowManagerReady(); + content::WindowedNotificationObserver lock_state_observer( + chrome::NOTIFICATION_SCREEN_LOCK_STATE_CHANGED, + content::NotificationService::AllSources()); + if (!tester->IsLocked()) + lock_state_observer.Wait(); + ScreenLocker* screen_locker = ScreenLocker::default_screen_locker(); + WebUIScreenLocker* web_ui_screen_locker = + static_cast<WebUIScreenLocker*>(screen_locker->delegate()); + ASSERT_TRUE(web_ui_screen_locker); + content::WebUI* web_ui = web_ui_screen_locker->GetWebUI(); + ASSERT_TRUE(web_ui); + contents_ = web_ui->GetWebContents(); + ASSERT_TRUE(contents_); + + // Wait for the login UI to be ready. + WaitUntilOobeUIIsReady( + static_cast<OobeUI*>(web_ui->GetController())); + } + + private: + scoped_ptr<ui::ScopedAnimationDurationScaleMode> zero_duration_mode_; + FakeSessionManagerClient* fake_session_manager_client_; + + DISALLOW_COPY_AND_ASSIGN(ShutdownPolicyLockerTest); +}; + +IN_PROC_BROWSER_TEST_F(ShutdownPolicyLockerTest, TestBasic) { + PrepareAndRunScript("restart-header-bar-item", true); + PrepareAndRunScript("shutdown-header-bar-item", false); +} + +IN_PROC_BROWSER_TEST_F(ShutdownPolicyLockerTest, PolicyChange) { + UpdateRebootOnShutdownPolicy(true); + RefreshDevicePolicy(); + PrepareAndRunScript("restart-header-bar-item", false); + PrepareAndRunScript("shutdown-header-bar-item", true); + + UpdateRebootOnShutdownPolicy(false); + RefreshDevicePolicy(); + PrepareAndRunScript("restart-header-bar-item", true); + PrepareAndRunScript("shutdown-header-bar-item", false); +} + +class ShutdownPolicyLoginTest : public ShutdownPolicyBaseTest { + protected: + ShutdownPolicyLoginTest() {} + ~ShutdownPolicyLoginTest() override {} + + // ShutdownPolicyBaseTest: + void SetUpCommandLine(base::CommandLine* command_line) override { + command_line->AppendSwitch(switches::kLoginManager); + command_line->AppendSwitch(switches::kForceLoginManagerInTests); + } + + void SetUpInProcessBrowserTestFixture() override { + ShutdownPolicyBaseTest::SetUpInProcessBrowserTestFixture(); + InstallOwnerKey(); + MarkAsEnterpriseOwned(); + } + + void SetUpOnMainThread() override { + ShutdownPolicyBaseTest::SetUpOnMainThread(); + + content::WindowedNotificationObserver( + chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE, + content::NotificationService::AllSources()).Wait(); + LoginDisplayHostImpl* host = + static_cast<LoginDisplayHostImpl*>( + LoginDisplayHostImpl::default_host()); + ASSERT_TRUE(host); + WebUILoginView* web_ui_login_view = host->GetWebUILoginView(); + ASSERT_TRUE(web_ui_login_view); + content::WebUI* web_ui = web_ui_login_view->GetWebUI(); + ASSERT_TRUE(web_ui); + contents_ = web_ui->GetWebContents(); + ASSERT_TRUE(contents_); + + // Wait for the login UI to be ready. + WaitUntilOobeUIIsReady(host->GetOobeUI()); + } + + void TearDownOnMainThread() override { + // If the login display is still showing, exit gracefully. + if (LoginDisplayHostImpl::default_host()) { + base::MessageLoop::current()->PostTask(FROM_HERE, + base::Bind(&chrome::AttemptExit)); + content::RunMessageLoop(); + } + } + + private: + DISALLOW_COPY_AND_ASSIGN(ShutdownPolicyLoginTest); +}; + +IN_PROC_BROWSER_TEST_F(ShutdownPolicyLoginTest, PolicyNotSet) { + PrepareAndRunScript("restart-header-bar-item", true); + PrepareAndRunScript("shutdown-header-bar-item", false); +} + +IN_PROC_BROWSER_TEST_F(ShutdownPolicyLoginTest, PolicyChange) { + UpdateRebootOnShutdownPolicy(true); + RefreshDevicePolicy(); + PrepareAndRunScript("restart-header-bar-item", false); + PrepareAndRunScript("shutdown-header-bar-item", true); + + UpdateRebootOnShutdownPolicy(false); + RefreshDevicePolicy(); + PrepareAndRunScript("restart-header-bar-item", true); + PrepareAndRunScript("shutdown-header-bar-item", false); +} + +} // namespace chromeos
diff --git a/chrome/browser/chromeos/system/input_device_settings_impl_x11.cc b/chrome/browser/chromeos/system/input_device_settings_impl_x11.cc index a4c05e4..aa41497a 100644 --- a/chrome/browser/chromeos/system/input_device_settings_impl_x11.cc +++ b/chrome/browser/chromeos/system/input_device_settings_impl_x11.cc
@@ -58,7 +58,7 @@ base::Process process = base::LaunchProcess(base::CommandLine(argv), base::LaunchOptions()); if (process.IsValid()) - base::EnsureProcessGetsReaped(process.pid()); + base::EnsureProcessGetsReaped(process.Pid()); } void ExecuteScript(const std::vector<std::string>& argv) {
diff --git a/chrome/browser/chromeos/system_logs/debug_log_writer.cc b/chrome/browser/chromeos/system_logs/debug_log_writer.cc index 3c31f6ec..1c2b089 100644 --- a/chrome/browser/chromeos/system_logs/debug_log_writer.cc +++ b/chrome/browser/chromeos/system_logs/debug_log_writer.cc
@@ -99,7 +99,7 @@ int exit_code = 0; if (!process.WaitForExit(&exit_code)) { - LOG(ERROR) << "Can't get exit code for pid " << process.pid(); + LOG(ERROR) << "Can't get exit code for pid " << process.Pid(); if (!callback.is_null()) callback.Run(false);
diff --git a/chrome/browser/component_updater/chrome_component_updater_configurator.cc b/chrome/browser/component_updater/chrome_component_updater_configurator.cc index efaa772..36f602d 100644 --- a/chrome/browser/component_updater/chrome_component_updater_configurator.cc +++ b/chrome/browser/component_updater/chrome_component_updater_configurator.cc
@@ -19,12 +19,15 @@ #include "chrome/browser/component_updater/component_patcher_operation_out_of_process.h" #include "chrome/browser/update_client/chrome_update_query_params_delegate.h" #include "chrome/common/chrome_version_info.h" -#include "components/component_updater/component_updater_configurator.h" #include "components/component_updater/component_updater_switches.h" +#include "components/update_client/configurator.h" #include "content/public/browser/browser_thread.h" #include "net/url_request/url_request_context_getter.h" #include "url/gurl.h" +using update_client::Configurator; +using update_client::OutOfProcessPatcher; + namespace component_updater { namespace {
diff --git a/chrome/browser/component_updater/chrome_component_updater_configurator.h b/chrome/browser/component_updater/chrome_component_updater_configurator.h index be80f3f..c3689c4 100644 --- a/chrome/browser/component_updater/chrome_component_updater_configurator.h +++ b/chrome/browser/component_updater/chrome_component_updater_configurator.h
@@ -5,7 +5,7 @@ #ifndef CHROME_BROWSER_COMPONENT_UPDATER_CHROME_COMPONENT_UPDATER_CONFIGURATOR_H_ #define CHROME_BROWSER_COMPONENT_UPDATER_CHROME_COMPONENT_UPDATER_CONFIGURATOR_H_ -#include "components/component_updater/component_updater_configurator.h" +#include "components/update_client/configurator.h" namespace base { class CommandLine; @@ -17,9 +17,7 @@ namespace component_updater { -class Configurator; - -Configurator* MakeChromeComponentUpdaterConfigurator( +update_client::Configurator* MakeChromeComponentUpdaterConfigurator( const base::CommandLine* cmdline, net::URLRequestContextGetter* context_getter);
diff --git a/chrome/browser/component_updater/component_patcher_operation_out_of_process.cc b/chrome/browser/component_updater/component_patcher_operation_out_of_process.cc index 12d1ed4..4242a48 100644 --- a/chrome/browser/component_updater/component_patcher_operation_out_of_process.cc +++ b/chrome/browser/component_updater/component_patcher_operation_out_of_process.cc
@@ -96,10 +96,10 @@ base::Callback<void(int result)> callback) { host_ = new PatchHost(callback, task_runner); scoped_ptr<IPC::Message> patch_message; - if (operation == kBsdiff) { + if (operation == update_client::kBsdiff) { patch_message.reset(new ChromeUtilityMsg_PatchFileBsdiff( input_abs_path, patch_abs_path, output_abs_path)); - } else if (operation == kCourgette) { + } else if (operation == update_client::kCourgette) { patch_message.reset(new ChromeUtilityMsg_PatchFileCourgette( input_abs_path, patch_abs_path, output_abs_path)); } else {
diff --git a/chrome/browser/component_updater/component_patcher_operation_out_of_process.h b/chrome/browser/component_updater/component_patcher_operation_out_of_process.h index 88c4c60..5500193 100644 --- a/chrome/browser/component_updater/component_patcher_operation_out_of_process.h +++ b/chrome/browser/component_updater/component_patcher_operation_out_of_process.h
@@ -10,7 +10,7 @@ #include "base/callback_forward.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "components/component_updater/component_patcher_operation.h" +#include "components/update_client/component_patcher_operation.h" namespace base { class FilePath; @@ -22,7 +22,7 @@ class PatchHost; // Implements the DeltaUpdateOpPatch out-of-process patching. -class ChromeOutOfProcessPatcher : public OutOfProcessPatcher { +class ChromeOutOfProcessPatcher : public update_client::OutOfProcessPatcher { public: ChromeOutOfProcessPatcher();
diff --git a/chrome/browser/component_updater/pepper_flash_component_installer.cc b/chrome/browser/component_updater/pepper_flash_component_installer.cc index 8ad0e25..fc9b092 100644 --- a/chrome/browser/component_updater/pepper_flash_component_installer.cc +++ b/chrome/browser/component_updater/pepper_flash_component_installer.cc
@@ -30,6 +30,7 @@ #include "chrome/common/chrome_switches.h" #include "chrome/common/pepper_flash.h" #include "components/component_updater/component_updater_service.h" +#include "components/update_client/update_client.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/plugin_service.h" #include "content/public/common/content_constants.h" @@ -330,7 +331,7 @@ } // namespace -class PepperFlashComponentInstaller : public ComponentInstaller { +class PepperFlashComponentInstaller : public update_client::ComponentInstaller { public: explicit PepperFlashComponentInstaller(const Version& version); @@ -438,7 +439,7 @@ void FinishPepperFlashUpdateRegistration(ComponentUpdateService* cus, const Version& version) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - CrxComponent pepflash; + update_client::CrxComponent pepflash; pepflash.name = "pepper_flash"; pepflash.installer = new PepperFlashComponentInstaller(version); pepflash.version = version;
diff --git a/chrome/browser/component_updater/pnacl/pnacl_component_installer.cc b/chrome/browser/component_updater/pnacl/pnacl_component_installer.cc index 25c74b7..90b831be 100644 --- a/chrome/browser/component_updater/pnacl/pnacl_component_installer.cc +++ b/chrome/browser/component_updater/pnacl/pnacl_component_installer.cc
@@ -32,6 +32,7 @@ #include "content/public/browser/browser_thread.h" using content::BrowserThread; +using update_client::CrxComponent; using update_client::UpdateQueryParams; namespace component_updater {
diff --git a/chrome/browser/component_updater/pnacl/pnacl_component_installer.h b/chrome/browser/component_updater/pnacl/pnacl_component_installer.h index fb5a614..a5683bb 100644 --- a/chrome/browser/component_updater/pnacl/pnacl_component_installer.h +++ b/chrome/browser/component_updater/pnacl/pnacl_component_installer.h
@@ -14,7 +14,7 @@ #include "base/macros.h" #include "base/memory/scoped_ptr.h" #include "base/version.h" -#include "components/component_updater/component_updater_service.h" +#include "components/update_client/update_client.h" namespace base { class DictionaryValue; @@ -32,10 +32,12 @@ namespace component_updater { +class ComponentUpdateService; + // Component installer responsible for Portable Native Client files. // Files can be installed to a shared location, or be installed to // a per-user location. -class PnaclComponentInstaller : public ComponentInstaller { +class PnaclComponentInstaller : public update_client::ComponentInstaller { public: PnaclComponentInstaller(); @@ -52,7 +54,7 @@ // Register a PNaCl component for the first time. void RegisterPnaclComponent(ComponentUpdateService* cus); - CrxComponent GetCrxComponent(); + update_client::CrxComponent GetCrxComponent(); // Determine the base directory for storing each version of PNaCl. base::FilePath GetPnaclBaseDirectory();
diff --git a/chrome/browser/component_updater/recovery_component_installer.cc b/chrome/browser/component_updater/recovery_component_installer.cc index 96fb8e6..2173f05f 100644 --- a/chrome/browser/component_updater/recovery_component_installer.cc +++ b/chrome/browser/component_updater/recovery_component_installer.cc
@@ -29,6 +29,7 @@ #include "components/component_updater/component_updater_paths.h" #include "components/component_updater/component_updater_service.h" #include "components/component_updater/pref_names.h" +#include "components/update_client/update_client.h" #include "content/public/browser/browser_thread.h" using content::BrowserThread; @@ -172,7 +173,7 @@ // There is a global error service monitors this flag and will pop up // bubble if the flag is set to true. // See chrome/browser/recovery/recovery_install_global_error.cc for details. -class RecoveryComponentInstaller : public ComponentInstaller { +class RecoveryComponentInstaller : public update_client::ComponentInstaller { public: RecoveryComponentInstaller(const Version& version, PrefService* prefs); ~RecoveryComponentInstaller() override {} @@ -205,7 +206,7 @@ return; } - CrxComponent recovery; + update_client::CrxComponent recovery; recovery.name = "recovery"; recovery.installer = new RecoveryComponentInstaller(version, prefs); recovery.version = version;
diff --git a/chrome/browser/component_updater/sw_reporter_installer_win.cc b/chrome/browser/component_updater/sw_reporter_installer_win.cc index ade986db..e64ee7b 100644 --- a/chrome/browser/component_updater/sw_reporter_installer_win.cc +++ b/chrome/browser/component_updater/sw_reporter_installer_win.cc
@@ -37,10 +37,11 @@ #include "chrome/common/pref_names.h" #include "components/component_updater/component_updater_paths.h" #include "components/component_updater/component_updater_service.h" -#include "components/component_updater/component_updater_utils.h" #include "components/component_updater/default_component_installer.h" #include "components/component_updater/pref_names.h" #include "components/pref_registry/pref_registry_syncable.h" +#include "components/update_client/update_client.h" +#include "components/update_client/utils.h" #include "content/public/browser/browser_thread.h" using content::BrowserThread; @@ -306,10 +307,10 @@ } static std::string ID() { - CrxComponent component; + update_client::CrxComponent component; component.version = Version("0.0.0.0"); GetPkHash(&component.pk_hash); - return component_updater::GetCrxComponentID(component); + return update_client::GetCrxComponentID(component); } static base::FilePath VersionPath() { return base::FilePath(version_dir_); } @@ -387,7 +388,7 @@ DCHECK_GT(elapsed.InMilliseconds(), 0); UMA_HISTOGRAM_BOOLEAN( "SoftwareReporter.Cleaner.HasRebooted", - static_cast<uint64>(elapsed.InMilliseconds()) > ::GetTickCount64()); + static_cast<uint64>(elapsed.InMilliseconds()) > ::GetTickCount()); } }
diff --git a/chrome/browser/component_updater/swiftshader_component_installer.cc b/chrome/browser/component_updater/swiftshader_component_installer.cc index e92fd0f1..bea146a5 100644 --- a/chrome/browser/component_updater/swiftshader_component_installer.cc +++ b/chrome/browser/component_updater/swiftshader_component_installer.cc
@@ -20,6 +20,7 @@ #include "base/values.h" #include "components/component_updater/component_updater_paths.h" #include "components/component_updater/component_updater_service.h" +#include "components/update_client/update_client.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/gpu_data_manager.h" #include "content/public/browser/gpu_data_manager_observer.h" @@ -95,7 +96,7 @@ GpuDataManager::GetInstance()->RegisterSwiftShaderPath(path); } -class SwiftShaderComponentInstaller : public ComponentInstaller { +class SwiftShaderComponentInstaller : public update_client::ComponentInstaller { public: explicit SwiftShaderComponentInstaller(const Version& version); @@ -165,7 +166,7 @@ const Version& version) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - CrxComponent swiftshader; + update_client::CrxComponent swiftshader; swiftshader.name = "Swift Shader"; swiftshader.installer = new SwiftShaderComponentInstaller(version); swiftshader.version = version;
diff --git a/chrome/browser/component_updater/test/component_updater_service_unittest.cc b/chrome/browser/component_updater/test/component_updater_service_unittest.cc index b3d1a413..7957c74 100644 --- a/chrome/browser/component_updater/test/component_updater_service_unittest.cc +++ b/chrome/browser/component_updater/test/component_updater_service_unittest.cc
@@ -16,10 +16,10 @@ #include "base/values.h" #include "chrome/browser/component_updater/component_updater_resource_throttle.h" #include "chrome/common/chrome_paths.h" -#include "components/component_updater/component_updater_utils.h" -#include "components/component_updater/test/test_configurator.h" -#include "components/component_updater/test/test_installer.h" -#include "components/component_updater/test/url_request_post_interceptor.h" +#include "components/update_client/test/test_configurator.h" +#include "components/update_client/test/test_installer.h" +#include "components/update_client/test/url_request_post_interceptor.h" +#include "components/update_client/utils.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/resource_controller.h" #include "content/public/browser/resource_request_info.h" @@ -34,11 +34,23 @@ using content::BrowserThread; using std::string; +using update_client::CrxComponent; +using update_client::PartialMatch; +using update_client::InterceptorFactory; +using update_client::TestConfigurator; +using update_client::TestInstaller; +using update_client::URLRequestPostInterceptor; +using update_client::VersionedTestInstaller; + using ::testing::_; using ::testing::AnyNumber; using ::testing::InSequence; using ::testing::Mock; +using update_client::abag_hash; +using update_client::ihfo_hash; +using update_client::jebg_hash; + namespace component_updater { MockServiceObserver::MockServiceObserver() { @@ -89,8 +101,11 @@ const base::FilePath ComponentUpdaterTest::test_file(const char* file) { base::FilePath path; PathService::Get(base::DIR_SOURCE_ROOT, &path); - return path.AppendASCII("components").AppendASCII("test").AppendASCII("data") - .AppendASCII("component_updater").AppendASCII(file); + return path.AppendASCII("components") + .AppendASCII("test") + .AppendASCII("data") + .AppendASCII("update_client") + .AppendASCII(file); } TestConfigurator* ComponentUpdaterTest::test_configurator() {
diff --git a/chrome/browser/component_updater/test/component_updater_service_unittest.h b/chrome/browser/component_updater/test/component_updater_service_unittest.h index 23b571ad..49550414 100644 --- a/chrome/browser/component_updater/test/component_updater_service_unittest.h +++ b/chrome/browser/component_updater/test/component_updater_service_unittest.h
@@ -20,12 +20,15 @@ class LocalHostTestURLRequestInterceptor; } -namespace component_updater { - +namespace update_client { +struct CrxComponent; class InterceptorFactory; class TestConfigurator; class TestInstaller; class URLRequestPostInterceptor; +} + +namespace component_updater { // Intercepts HTTP GET requests sent to "localhost". typedef net::LocalHostTestURLRequestInterceptor GetInterceptor; @@ -51,24 +54,27 @@ // Makes the full path to a component updater test file. const base::FilePath test_file(const char* file); - TestConfigurator* test_configurator(); + update_client::TestConfigurator* test_configurator(); - ComponentUpdateService::Status RegisterComponent(CrxComponent* com, - TestComponents component, - const Version& version, - TestInstaller* installer); + ComponentUpdateService::Status RegisterComponent( + update_client::CrxComponent* com, + TestComponents component, + const Version& version, + update_client::TestInstaller* installer); protected: void RunThreads(); void RunThreadsUntilIdle(); - scoped_ptr<InterceptorFactory> interceptor_factory_; - URLRequestPostInterceptor* post_interceptor_; // Owned by the factory. + scoped_ptr<update_client::InterceptorFactory> interceptor_factory_; + + // Owned by the factory. + update_client::URLRequestPostInterceptor* post_interceptor_; scoped_ptr<GetInterceptor> get_interceptor_; private: - TestConfigurator* test_config_; + update_client::TestConfigurator* test_config_; content::TestBrowserThreadBundle thread_bundle_; scoped_ptr<ComponentUpdateService> component_updater_; };
diff --git a/chrome/browser/component_updater/test/supervised_user_whitelist_installer_unittest.cc b/chrome/browser/component_updater/test/supervised_user_whitelist_installer_unittest.cc index 9eb3a16e..1f0ef1f 100644 --- a/chrome/browser/component_updater/test/supervised_user_whitelist_installer_unittest.cc +++ b/chrome/browser/component_updater/test/supervised_user_whitelist_installer_unittest.cc
@@ -18,11 +18,16 @@ #include "chrome/browser/component_updater/supervised_user_whitelist_installer.h" #include "components/component_updater/component_updater_paths.h" #include "components/component_updater/component_updater_service.h" -#include "components/component_updater/component_updater_utils.h" #include "components/crx_file/id_util.h" +#include "components/update_client/crx_update_item.h" +#include "components/update_client/update_client.h" +#include "components/update_client/utils.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +using update_client::CrxComponent; +using update_client::CrxUpdateItem; + namespace component_updater { namespace {
diff --git a/chrome/browser/devtools/device/usb/android_usb_browsertest.cc b/chrome/browser/devtools/device/usb/android_usb_browsertest.cc index f302de9..af2dd46 100644 --- a/chrome/browser/devtools/device/usb/android_usb_browsertest.cc +++ b/chrome/browser/devtools/device/usb/android_usb_browsertest.cc
@@ -35,11 +35,20 @@ namespace { +struct NoConfigTraits { + static const int kClass = 0xff; + static const int kSubclass = 0x42; + static const int kProtocol = 0x1; + static const bool kBreaks = false; + static const bool kConfigured = false; +}; + struct AndroidTraits { static const int kClass = 0xff; static const int kSubclass = 0x42; static const int kProtocol = 0x1; static const bool kBreaks = false; + static const bool kConfigured = true; }; struct NonAndroidTraits { @@ -47,6 +56,7 @@ static const int kSubclass = 0x42; static const int kProtocol = 0x2; static const bool kBreaks = false; + static const bool kConfigured = true; }; struct BreakingAndroidTraits { @@ -54,6 +64,7 @@ static const int kSubclass = 0x42; static const int kProtocol = 0x1; static const bool kBreaks = true; + static const bool kConfigured = true; }; const uint32 kMaxPayload = 4096; @@ -400,7 +411,7 @@ } virtual const UsbConfigDescriptor* GetConfiguration() override { - return &config_desc_; + return T::kConfigured ? &config_desc_ : nullptr; } virtual bool GetManufacturer(base::string16* manufacturer) override { @@ -475,6 +486,20 @@ } }; +class MockNoConfigUsbService : public UsbService { + public: + scoped_refptr<UsbDevice> GetDeviceById(uint32 unique_id) override { + NOTIMPLEMENTED(); + return nullptr; + } + + void GetDevices(std::vector<scoped_refptr<UsbDevice>>* devices) override { + STLClearObject(devices); + devices->push_back(new MockUsbDevice<AndroidTraits>()); + devices->push_back(new MockUsbDevice<NoConfigTraits>()); + } +}; + class MockUsbServiceForCheckingTraits : public UsbService { public: MockUsbServiceForCheckingTraits() : step_(0) {} @@ -612,6 +637,13 @@ } }; +class AndroidNoConfigUsbTest : public AndroidUsbDiscoveryTest { + protected: + void SetUpService() override { + UsbService::SetInstanceForTest(new MockNoConfigUsbService()); + } +}; + class MockListListener : public DevToolsAndroidBridge::DeviceListListener { public: MockListListener(DevToolsAndroidBridge* adb_bridge, @@ -787,6 +819,12 @@ runner_->Run(); } +IN_PROC_BROWSER_TEST_F(AndroidNoConfigUsbTest, TestDeviceNoConfig) { + MockListListener listener(adb_bridge_, runner_->QuitClosure()); + adb_bridge_->AddDeviceListListener(&listener); + runner_->Run(); +} + IN_PROC_BROWSER_TEST_F(AndroidUsbCountTest, TestNoMultipleCallsRemoveInCallback) { MockCountListener listener(adb_bridge_);
diff --git a/chrome/browser/devtools/device/usb/android_usb_device.cc b/chrome/browser/devtools/device/usb/android_usb_device.cc index 2e8b91d..0ff40cd 100644 --- a/chrome/browser/devtools/device/usb/android_usb_device.cc +++ b/chrome/browser/devtools/device/usb/android_usb_device.cc
@@ -78,16 +78,14 @@ int outbound_address = 0; int zero_mask = 0; - for (UsbEndpointDescriptor::Iterator endpointIt = interface.endpoints.begin(); - endpointIt != interface.endpoints.end(); - ++endpointIt) { - if (endpointIt->transfer_type != device::USB_TRANSFER_BULK) + for (const UsbEndpointDescriptor& endpoint : interface.endpoints) { + if (endpoint.transfer_type != device::USB_TRANSFER_BULK) continue; - if (endpointIt->direction == device::USB_DIRECTION_INBOUND) - inbound_address = endpointIt->address; + if (endpoint.direction == device::USB_DIRECTION_INBOUND) + inbound_address = endpoint.address; else - outbound_address = endpointIt->address; - zero_mask = endpointIt->maximum_packet_size - 1; + outbound_address = endpoint.address; + zero_mask = endpoint.maximum_packet_size - 1; } if (inbound_address == 0 || outbound_address == 0) @@ -169,9 +167,8 @@ scoped_ptr<AndroidUsbDevices> devices(new_devices); // Add raw pointers to the newly claimed devices. - for (AndroidUsbDevices::iterator it = devices->begin(); it != devices->end(); - ++it) { - g_devices.Get().push_back(it->get()); + for (const scoped_refptr<AndroidUsbDevice>& device : *devices) { + g_devices.Get().push_back(device.get()); } // Return all claimed devices. @@ -207,7 +204,7 @@ scoped_refptr<AndroidUsbDevice> android_device = ClaimInterface( rsa_key, usb_handle, serial, config->interfaces[interface_id]); if (android_device.get()) - devices->push_back(android_device.get()); + devices->push_back(android_device); else usb_handle->Close(); } @@ -259,6 +256,7 @@ for (const scoped_refptr<UsbDevice>& device : usb_devices) { const UsbConfigDescriptor* config = device->GetConfiguration(); if (!config) { + barrier.Run(); continue; } bool has_android_interface = false; @@ -299,12 +297,11 @@ const AndroidUsbDevicesCallback& callback) { // Collect devices with closed handles. - for (std::vector<AndroidUsbDevice*>::iterator it = g_devices.Get().begin(); - it != g_devices.Get().end(); ++it) { - if ((*it)->usb_handle_.get()) { + for (AndroidUsbDevice* device : g_devices.Get()) { + if (device->usb_handle_.get()) { BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, - base::Bind(&AndroidUsbDevice::TerminateIfReleased, *it, - (*it)->usb_handle_)); + base::Bind(&AndroidUsbDevice::TerminateIfReleased, device, + device->usb_handle_)); } }
diff --git a/chrome/browser/devtools/devtools_ui_bindings.cc b/chrome/browser/devtools/devtools_ui_bindings.cc index 36b27788..c542b515 100644 --- a/chrome/browser/devtools/devtools_ui_bindings.cc +++ b/chrome/browser/devtools/devtools_ui_bindings.cc
@@ -249,7 +249,8 @@ // TODO(creis): Replace with RenderFrameCreated when http://crbug.com/425397 // is fixed. See also http://crbug.com/424641. void AboutToNavigateRenderFrame( - content::RenderFrameHost* render_frame_host) override; + content::RenderFrameHost* old_host, + content::RenderFrameHost* new_host) override; void DocumentOnLoadCompletedInMainFrame() override; void DidNavigateMainFrame( const content::LoadCommittedDetails& details, @@ -287,11 +288,12 @@ } void DevToolsUIBindings::FrontendWebContentsObserver:: - AboutToNavigateRenderFrame(content::RenderFrameHost* render_frame_host) { - if (render_frame_host->GetParent()) + AboutToNavigateRenderFrame(content::RenderFrameHost* old_host, + content::RenderFrameHost* new_host) { + if (new_host->GetParent()) return; devtools_bindings_->frontend_host_.reset( - content::DevToolsFrontendHost::Create(render_frame_host, + content::DevToolsFrontendHost::Create(new_host, devtools_bindings_)); }
diff --git a/chrome/browser/devtools/devtools_window.cc b/chrome/browser/devtools/devtools_window.cc index cbdd1451..f3c189c5 100644 --- a/chrome/browser/devtools/devtools_window.cc +++ b/chrome/browser/devtools/devtools_window.cc
@@ -20,9 +20,11 @@ #include "chrome/browser/ui/browser_dialogs.h" #include "chrome/browser/ui/browser_iterator.h" #include "chrome/browser/ui/browser_list.h" +#include "chrome/browser/ui/browser_tabstrip.h" #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/host_desktop.h" #include "chrome/browser/ui/prefs/prefs_tab_helper.h" +#include "chrome/browser/ui/scoped_tabbed_browser_displayer.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/webui/devtools_ui.h" #include "chrome/common/chrome_switches.h" @@ -1027,28 +1029,13 @@ GURL(url), content::Referrer(), NEW_FOREGROUND_TAB, ui::PAGE_TRANSITION_LINK, false); WebContents* inspected_web_contents = GetInspectedWebContents(); - if (inspected_web_contents) { - inspected_web_contents->OpenURL(params); - } else { - chrome::HostDesktopType host_desktop_type; - if (browser_) { - host_desktop_type = browser_->host_desktop_type(); - } else { - // There should always be a browser when there are no inspected web - // contents. - NOTREACHED(); - host_desktop_type = chrome::GetActiveDesktop(); - } + if (!inspected_web_contents || !inspected_web_contents->OpenURL(params)) { + chrome::HostDesktopType host_desktop_type = + browser_ ? browser_->host_desktop_type() : chrome::GetActiveDesktop(); - const BrowserList* browser_list = - BrowserList::GetInstance(host_desktop_type); - for (BrowserList::const_iterator it = browser_list->begin(); - it != browser_list->end(); ++it) { - if ((*it)->type() == Browser::TYPE_TABBED) { - (*it)->OpenURL(params); - break; - } - } + chrome::ScopedTabbedBrowserDisplayer displayer(profile_, host_desktop_type); + chrome::AddSelectedTabWithURL(displayer.browser(), GURL(url), + ui::PAGE_TRANSITION_LINK); } }
diff --git a/chrome/browser/drive/drive_api_service.cc b/chrome/browser/drive/drive_api_service.cc index cd878d3a..66faaba 100644 --- a/chrome/browser/drive/drive_api_service.cc +++ b/chrome/browser/drive/drive_api_service.cc
@@ -13,7 +13,6 @@ #include "google_apis/drive/auth_service.h" #include "google_apis/drive/drive_api_parser.h" #include "google_apis/drive/drive_api_requests.h" -#include "google_apis/drive/gdata_errorcode.h" #include "google_apis/drive/request_sender.h" #include "google_apis/google_api_keys.h" #include "net/url_request/url_request_context_getter.h" @@ -166,13 +165,11 @@ base::SequencedTaskRunner* blocking_task_runner, const GURL& base_url, const GURL& base_download_url, - const GURL& wapi_base_url, const std::string& custom_user_agent) : oauth2_token_service_(oauth2_token_service), url_request_context_getter_(url_request_context_getter), blocking_task_runner_(blocking_task_runner), url_generator_(base_url, base_download_url), - wapi_url_generator_(wapi_base_url), custom_user_agent_(custom_user_agent) { }
diff --git a/chrome/browser/drive/drive_api_service.h b/chrome/browser/drive/drive_api_service.h index 7f39d1c..ffe26bc 100644 --- a/chrome/browser/drive/drive_api_service.h +++ b/chrome/browser/drive/drive_api_service.h
@@ -15,7 +15,6 @@ #include "google_apis/drive/auth_service_interface.h" #include "google_apis/drive/auth_service_observer.h" #include "google_apis/drive/drive_api_url_generator.h" -#include "google_apis/drive/gdata_wapi_url_generator.h" class GURL; class OAuth2TokenService; @@ -47,9 +46,6 @@ // |base_url| is used to generate URLs for communication with the drive API. // |base_download_url| is used to generate URLs for downloading file from the // drive API. - // |wapi_base_url| is used to generate URLs for shared_url. Unfortunately, - // the share_url is not yet supported on Drive API v2, so as a fallback, - // we use GData WAPI. // |custom_user_agent| will be used for the User-Agent header in HTTP // requests issues through the service if the value is not empty. DriveAPIService( @@ -58,7 +54,6 @@ base::SequencedTaskRunner* blocking_task_runner, const GURL& base_url, const GURL& base_download_url, - const GURL& wapi_base_url, const std::string& custom_user_agent); ~DriveAPIService() override; @@ -214,7 +209,6 @@ scoped_ptr<google_apis::RequestSender> sender_; ObserverList<DriveServiceObserver> observers_; google_apis::DriveApiUrlGenerator url_generator_; - google_apis::GDataWapiUrlGenerator wapi_url_generator_; const std::string custom_user_agent_; DISALLOW_COPY_AND_ASSIGN(DriveAPIService);
diff --git a/chrome/browser/drive/drive_api_util.cc b/chrome/browser/drive/drive_api_util.cc index f5245dd5..2d58930 100644 --- a/chrome/browser/drive/drive_api_util.cc +++ b/chrome/browser/drive/drive_api_util.cc
@@ -121,11 +121,6 @@ return result; } -std::string ExtractResourceIdFromUrl(const GURL& url) { - return net::UnescapeURLComponent(url.ExtractFileName(), - net::UnescapeRule::URL_SPECIAL_CHARS); -} - std::string CanonicalizeResourceId(const std::string& resource_id) { // If resource ID is in the old WAPI format starting with a prefix like // "document:", strip it and return the remaining part. @@ -143,7 +138,6 @@ // ResourceEntry entry->set_resource_id(file_resource.file_id()); - entry->set_id(file_resource.file_id()); if (file_resource.IsDirectory()) entry->set_kind(google_apis::ResourceEntry::ENTRY_KIND_FOLDER); else if (file_resource.IsHostedDocument()) @@ -151,132 +145,15 @@ else entry->set_kind(google_apis::ResourceEntry::ENTRY_KIND_FILE); entry->set_title(file_resource.title()); - entry->set_published_time(file_resource.created_date()); - - std::vector<std::string> labels; - if (!file_resource.shared_with_me_date().is_null()) - labels.push_back("shared-with-me"); - if (file_resource.shared()) - labels.push_back("shared"); - entry->set_labels(labels); - - // This should be the url to download the file_resource. - { - google_apis::Content content; - content.set_mime_type(file_resource.mime_type()); - entry->set_content(content); - } - // TODO(kochi): entry->resource_links_ - - // For file entries - entry->set_filename(file_resource.title()); - entry->set_suggested_filename(file_resource.title()); - entry->set_file_md5(file_resource.md5_checksum()); - entry->set_file_size(file_resource.file_size()); // If file is removed completely, that information is only available in // ChangeResource, and is reflected in |removed_|. If file is trashed, the // file entry still exists but with its "trashed" label true. entry->set_deleted(file_resource.labels().is_trashed()); - // ImageMediaMetadata - entry->set_image_width(file_resource.image_media_metadata().width()); - entry->set_image_height(file_resource.image_media_metadata().height()); - entry->set_image_rotation(file_resource.image_media_metadata().rotation()); - - // CommonMetadata - entry->set_etag(file_resource.etag()); - // entry->authors_ - // entry->links_. - ScopedVector<google_apis::Link> links; - for (size_t i = 0; i < file_resource.parents().size(); ++i) { - google_apis::Link* link = new google_apis::Link; - link->set_type(google_apis::Link::LINK_PARENT); - link->set_href(file_resource.parents()[i].parent_link()); - links.push_back(link); - } - if (!file_resource.alternate_link().is_empty()) { - google_apis::Link* link = new google_apis::Link; - link->set_type(google_apis::Link::LINK_ALTERNATE); - link->set_href(file_resource.alternate_link()); - links.push_back(link); - } - entry->set_links(links.Pass()); - - // entry->categories_ - entry->set_updated_time(file_resource.modified_date()); - entry->set_last_viewed_time(file_resource.last_viewed_by_me_date()); - - entry->FillRemainingFields(); return entry.Pass(); } -scoped_ptr<google_apis::ResourceEntry> -ConvertChangeResourceToResourceEntry( - const google_apis::ChangeResource& change_resource) { - scoped_ptr<google_apis::ResourceEntry> entry; - if (change_resource.file()) - entry = ConvertFileResourceToResourceEntry(*change_resource.file()).Pass(); - else - entry.reset(new google_apis::ResourceEntry); - - entry->set_resource_id(change_resource.file_id()); - // If |is_deleted()| returns true, the file is removed from Drive. - entry->set_removed(change_resource.is_deleted()); - entry->set_changestamp(change_resource.change_id()); - entry->set_modification_date(change_resource.modification_date()); - - return entry.Pass(); -} - -scoped_ptr<google_apis::ResourceList> -ConvertFileListToResourceList(const google_apis::FileList& file_list) { - scoped_ptr<google_apis::ResourceList> feed(new google_apis::ResourceList); - - const ScopedVector<google_apis::FileResource>& items = file_list.items(); - ScopedVector<google_apis::ResourceEntry> entries; - for (size_t i = 0; i < items.size(); ++i) - entries.push_back(ConvertFileResourceToResourceEntry(*items[i]).release()); - feed->set_entries(entries.Pass()); - - ScopedVector<google_apis::Link> links; - if (!file_list.next_link().is_empty()) { - google_apis::Link* link = new google_apis::Link; - link->set_type(google_apis::Link::LINK_NEXT); - link->set_href(file_list.next_link()); - links.push_back(link); - } - feed->set_links(links.Pass()); - - return feed.Pass(); -} - -scoped_ptr<google_apis::ResourceList> -ConvertChangeListToResourceList(const google_apis::ChangeList& change_list) { - scoped_ptr<google_apis::ResourceList> feed(new google_apis::ResourceList); - - const ScopedVector<google_apis::ChangeResource>& items = change_list.items(); - ScopedVector<google_apis::ResourceEntry> entries; - for (size_t i = 0; i < items.size(); ++i) { - entries.push_back( - ConvertChangeResourceToResourceEntry(*items[i]).release()); - } - feed->set_entries(entries.Pass()); - - feed->set_largest_changestamp(change_list.largest_change_id()); - - ScopedVector<google_apis::Link> links; - if (!change_list.next_link().is_empty()) { - google_apis::Link* link = new google_apis::Link; - link->set_type(google_apis::Link::LINK_NEXT); - link->set_href(change_list.next_link()); - links.push_back(link); - } - feed->set_links(links.Pass()); - - return feed.Pass(); -} - std::string GetMd5Digest(const base::FilePath& file_path) { const int kBufferSize = 512 * 1024; // 512kB.
diff --git a/chrome/browser/drive/drive_api_util.h b/chrome/browser/drive/drive_api_util.h index 008328b0..9705745 100644 --- a/chrome/browser/drive/drive_api_util.h +++ b/chrome/browser/drive/drive_api_util.h
@@ -24,7 +24,6 @@ class FileList; class FileResource; class ResourceEntry; -class ResourceList; } // namespace google_apis namespace drive { @@ -57,9 +56,6 @@ // See also: https://developers.google.com/drive/search-parameters std::string TranslateQuery(const std::string& original_query); -// Extracts resource_id out of edit url. -std::string ExtractResourceIdFromUrl(const GURL& url); - // If |resource_id| is in the old resource ID format used by WAPI, converts it // into the new format. std::string CanonicalizeResourceId(const std::string& resource_id); @@ -69,19 +65,6 @@ ConvertFileResourceToResourceEntry( const google_apis::FileResource& file_resource); -// Converts ChangeResource to ResourceEntry. -scoped_ptr<google_apis::ResourceEntry> -ConvertChangeResourceToResourceEntry( - const google_apis::ChangeResource& change_resource); - -// Converts FileList to ResourceList. -scoped_ptr<google_apis::ResourceList> -ConvertFileListToResourceList(const google_apis::FileList& file_list); - -// Converts ChangeList to ResourceList. -scoped_ptr<google_apis::ResourceList> -ConvertChangeListToResourceList(const google_apis::ChangeList& change_list); - // Returns the (base-16 encoded) MD5 digest of the file content at |file_path|, // or an empty string if an error is found. std::string GetMd5Digest(const base::FilePath& file_path);
diff --git a/chrome/browser/drive/drive_api_util_unittest.cc b/chrome/browser/drive/drive_api_util_unittest.cc index d8e9f8a..70592f4 100644 --- a/chrome/browser/drive/drive_api_util_unittest.cc +++ b/chrome/browser/drive/drive_api_util_unittest.cc
@@ -7,7 +7,6 @@ #include "base/files/scoped_temp_dir.h" #include "base/md5.h" #include "google_apis/drive/drive_api_parser.h" -#include "google_apis/drive/gdata_wapi_parser.h" #include "google_apis/drive/test_util.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" @@ -53,17 +52,6 @@ EXPECT_EQ("fullText contains 'dog'", TranslateQuery("\"\" dog \"\"")); } -TEST(FileSystemUtilTest, ExtractResourceIdFromUrl) { - EXPECT_EQ("file:2_file_resource_id", ExtractResourceIdFromUrl( - GURL("https://file1_link_self/file:2_file_resource_id"))); - // %3A should be unescaped. - EXPECT_EQ("file:2_file_resource_id", ExtractResourceIdFromUrl( - GURL("https://file1_link_self/file%3A2_file_resource_id"))); - - // The resource ID cannot be extracted, hence empty. - EXPECT_EQ("", ExtractResourceIdFromUrl(GURL("https://www.example.com/"))); -} - TEST(FileSystemUtilTest, CanonicalizeResourceId) { std::string resource_id("1YsCnrMxxgp7LDdtlFDt-WdtEIth89vA9inrILtvK-Ug"); @@ -79,80 +67,6 @@ EXPECT_EQ(resource_id, CanonicalizeResourceId("externalapp:" + resource_id)); } -TEST(FileSystemUtilTest, ConvertFileResourceToResource_Parents) { - google_apis::FileResource file_resource; - - std::vector<GURL> expected_links; - expected_links.push_back(GURL("http://server/id1")); - expected_links.push_back(GURL("http://server/id2")); - expected_links.push_back(GURL("http://server/id3")); - - for (size_t i = 0; i < expected_links.size(); ++i) { - google_apis::ParentReference parent; - parent.set_parent_link(expected_links[i]); - file_resource.mutable_parents()->push_back(parent); - } - - scoped_ptr<google_apis::ResourceEntry> entry( - ConvertFileResourceToResourceEntry(file_resource)); - std::vector<GURL> actual_links; - for (size_t i = 0; i < entry->links().size(); ++i) { - if (entry->links()[i]->type() == google_apis::Link::LINK_PARENT) - actual_links.push_back(entry->links()[i]->href()); - } - - EXPECT_EQ(expected_links, actual_links); -} - -TEST(FileSystemUtilTest, ConvertFileResourceToResourceEntryImageMediaMetadata) { - google_apis::FileResource file_resource_all_fields; - google_apis::FileResource file_resource_zero_fields; - google_apis::FileResource file_resource_no_fields; - // Set up FileResource instances; - { - { - google_apis::ImageMediaMetadata* image_media_metadata = - file_resource_all_fields.mutable_image_media_metadata(); - image_media_metadata->set_width(640); - image_media_metadata->set_height(480); - image_media_metadata->set_rotation(90); - } - { - google_apis::ImageMediaMetadata* image_media_metadata = - file_resource_zero_fields.mutable_image_media_metadata(); - image_media_metadata->set_width(0); - image_media_metadata->set_height(0); - image_media_metadata->set_rotation(0); - } - } - - // Verify the converted values. - { - scoped_ptr<google_apis::ResourceEntry> resource_entry( - ConvertFileResourceToResourceEntry(file_resource_all_fields)); - - EXPECT_EQ(640, resource_entry->image_width()); - EXPECT_EQ(480, resource_entry->image_height()); - EXPECT_EQ(90, resource_entry->image_rotation()); - } - { - scoped_ptr<google_apis::ResourceEntry> resource_entry( - ConvertFileResourceToResourceEntry(file_resource_zero_fields)); - - EXPECT_EQ(0, resource_entry->image_width()); - EXPECT_EQ(0, resource_entry->image_height()); - EXPECT_EQ(0, resource_entry->image_rotation()); - } - { - scoped_ptr<google_apis::ResourceEntry> resource_entry( - ConvertFileResourceToResourceEntry(file_resource_no_fields)); - - EXPECT_EQ(-1, resource_entry->image_width()); - EXPECT_EQ(-1, resource_entry->image_height()); - EXPECT_EQ(-1, resource_entry->image_rotation()); - } -} - TEST(DriveAPIUtilTest, GetMd5Digest) { base::ScopedTempDir temp_dir; ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
diff --git a/chrome/browser/extensions/api/browsing_data/browsing_data_test.cc b/chrome/browser/extensions/api/browsing_data/browsing_data_test.cc index 8cece520f..aa702c1d 100644 --- a/chrome/browser/extensions/api/browsing_data/browsing_data_test.cc +++ b/chrome/browser/extensions/api/browsing_data/browsing_data_test.cc
@@ -13,14 +13,12 @@ #include "base/values.h" #include "chrome/browser/browsing_data/browsing_data_helper.h" #include "chrome/browser/browsing_data/browsing_data_remover.h" -#include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/extensions/api/browsing_data/browsing_data_api.h" #include "chrome/browser/extensions/extension_function_test_utils.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" #include "chrome/common/pref_names.h" #include "chrome/test/base/in_process_browser_test.h" -#include "content/public/browser/notification_service.h" using extension_function_test_utils::RunFunctionAndReturnError; using extension_function_test_utils::RunFunctionAndReturnSingleResult; @@ -42,8 +40,7 @@ "}]"; -class ExtensionBrowsingDataTest : public InProcessBrowserTest, - public content::NotificationObserver { +class ExtensionBrowsingDataTest : public InProcessBrowserTest { public: base::Time GetBeginTime() { return called_with_details_->removal_begin; @@ -60,21 +57,19 @@ protected: void SetUpOnMainThread() override { called_with_details_.reset(new BrowsingDataRemover::NotificationDetails()); - registrar_.Add(this, chrome::NOTIFICATION_BROWSING_DATA_REMOVED, - content::Source<Profile>(browser()->profile())); + callback_subscription_ = + BrowsingDataRemover::RegisterOnBrowsingDataRemovedCallback( + base::Bind(&ExtensionBrowsingDataTest::NotifyWithDetails, + base::Unretained(this))); } - // content::NotificationObserver implementation. - void Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) override { - DCHECK_EQ(type, chrome::NOTIFICATION_BROWSING_DATA_REMOVED); - + // Callback for browsing data removal events. + void NotifyWithDetails( + const BrowsingDataRemover::NotificationDetails& details) { // We're not taking ownership of the details object, but storing a copy of // it locally. - called_with_details_.reset(new BrowsingDataRemover::NotificationDetails( - *content::Details<BrowsingDataRemover::NotificationDetails>( - details).ptr())); + called_with_details_.reset( + new BrowsingDataRemover::NotificationDetails(details)); } int GetAsMask(const base::DictionaryValue* dict, std::string path, @@ -257,7 +252,9 @@ private: scoped_ptr<BrowsingDataRemover::NotificationDetails> called_with_details_; - content::NotificationRegistrar registrar_; + + BrowsingDataRemover::CallbackSubscription callback_subscription_; + }; } // namespace
diff --git a/chrome/browser/extensions/api/content_settings/content_settings_apitest.cc b/chrome/browser/extensions/api/content_settings/content_settings_apitest.cc index e7525e5..5bf6bc47 100644 --- a/chrome/browser/extensions/api/content_settings/content_settings_apitest.cc +++ b/chrome/browser/extensions/api/content_settings/content_settings_apitest.cc
@@ -106,6 +106,11 @@ example_url, CONTENT_SETTINGS_TYPE_NOTIFICATIONS, std::string())); + EXPECT_EQ(CONTENT_SETTING_ASK, + map->GetContentSetting(example_url, + example_url, + CONTENT_SETTINGS_TYPE_MOUSELOCK, + std::string())); // Check content settings for www.google.com GURL url("http://www.google.com"); @@ -129,6 +134,9 @@ CONTENT_SETTING_BLOCK, map->GetContentSetting( url, url, CONTENT_SETTINGS_TYPE_NOTIFICATIONS, std::string())); + EXPECT_EQ(CONTENT_SETTING_BLOCK, + map->GetContentSetting( + url, url, CONTENT_SETTINGS_TYPE_MOUSELOCK, std::string())); } void CheckContentSettingsDefault() { @@ -161,6 +169,9 @@ CONTENT_SETTING_ASK, map->GetContentSetting( url, url, CONTENT_SETTINGS_TYPE_NOTIFICATIONS, std::string())); + EXPECT_EQ(CONTENT_SETTING_ASK, + map->GetContentSetting( + url, url, CONTENT_SETTINGS_TYPE_MOUSELOCK, std::string())); } private:
diff --git a/chrome/browser/extensions/api/content_settings/content_settings_helpers.cc b/chrome/browser/extensions/api/content_settings/content_settings_helpers.cc index 7fc2e85..7730dc2d 100644 --- a/chrome/browser/extensions/api/content_settings/content_settings_helpers.cc +++ b/chrome/browser/extensions/api/content_settings/content_settings_helpers.cc
@@ -25,7 +25,13 @@ "popups", "location", "notifications", + "auto-select-certificate", + "fullscreen", + "mouselock" }; + +// TODO(msramek): Assert that |kContentSettingsTypeNames| is synced with enum +// |ContentSettingsType| and mapping in |kContentSettingsTypeGroupNames|. static_assert(arraysize(kContentSettingsTypeNames) <= CONTENT_SETTINGS_NUM_TYPES, "kContentSettingsTypeNames has an unexpected number of elements");
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_api.cc b/chrome/browser/extensions/api/developer_private/developer_private_api.cc index 70ac235..b87d566 100644 --- a/chrome/browser/extensions/api/developer_private/developer_private_api.cc +++ b/chrome/browser/extensions/api/developer_private/developer_private_api.cc
@@ -70,12 +70,12 @@ #include "extensions/common/switches.h" #include "extensions/grit/extensions_browser_resources.h" #include "net/base/net_util.h" +#include "storage/browser/blob/shareable_file_reference.h" #include "storage/browser/fileapi/external_mount_points.h" #include "storage/browser/fileapi/file_system_context.h" #include "storage/browser/fileapi/file_system_operation.h" #include "storage/browser/fileapi/file_system_operation_runner.h" #include "storage/browser/fileapi/isolated_context.h" -#include "storage/common/blob/shareable_file_reference.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/webui/web_ui_util.h"
diff --git a/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.cc b/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.cc index 8bb7dec2..f4b8f745 100644 --- a/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.cc +++ b/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.cc
@@ -10,6 +10,7 @@ #include "chrome/browser/chromeos/platform_keys/platform_keys.h" #include "chrome/browser/chromeos/platform_keys/platform_keys_service.h" #include "chrome/browser/chromeos/platform_keys/platform_keys_service_factory.h" +#include "chrome/browser/extensions/api/platform_keys/platform_keys_api.h" #include "chrome/common/extensions/api/enterprise_platform_keys.h" #include "chrome/common/extensions/api/enterprise_platform_keys_internal.h" #include "content/public/browser/browser_thread.h" @@ -24,39 +25,10 @@ // This error will occur if a token is removed and will be exposed to the // extension. Keep this in sync with the custom binding in Javascript. -const char kErrorInvalidToken[] = "The token is not valid."; - const char kErrorInternal[] = "Internal Error."; -const char kErrorAlgorithmNotSupported[] = "Algorithm not supported."; + const char kErrorInvalidX509Cert[] = "Certificate is not a valid X.509 certificate."; -const char kTokenIdUser[] = "user"; -const char kTokenIdSystem[] = "system"; - -// Returns whether |token_id| references a known Token. -bool ValidateToken(const std::string& token_id, - std::string* platform_keys_token_id) { - platform_keys_token_id->clear(); - if (token_id == kTokenIdUser) { - *platform_keys_token_id = chromeos::platform_keys::kTokenIdUser; - return true; - } - if (token_id == kTokenIdSystem) { - *platform_keys_token_id = chromeos::platform_keys::kTokenIdSystem; - return true; - } - return false; -} - -std::string PlatformKeysTokenIdToApiId( - const std::string& platform_keys_token_id) { - if (platform_keys_token_id == chromeos::platform_keys::kTokenIdUser) - return kTokenIdUser; - if (platform_keys_token_id == chromeos::platform_keys::kTokenIdSystem) - return kTokenIdSystem; - - return std::string(); -} } // namespace @@ -71,8 +43,8 @@ // TODO(pneubeck): Add support for unsigned integers to IDL. EXTENSION_FUNCTION_VALIDATE(params && params->modulus_length >= 0); std::string platform_keys_token_id; - if (!ValidateToken(params->token_id, &platform_keys_token_id)) - return RespondNow(Error(kErrorInvalidToken)); + if (!platform_keys::ValidateToken(params->token_id, &platform_keys_token_id)) + return RespondNow(Error(platform_keys::kErrorInvalidToken)); chromeos::PlatformKeysService* service = chromeos::PlatformKeysServiceFactory::GetForBrowserContext( @@ -101,57 +73,6 @@ } } -EnterprisePlatformKeysInternalSignFunction:: - ~EnterprisePlatformKeysInternalSignFunction() { -} - -ExtensionFunction::ResponseAction -EnterprisePlatformKeysInternalSignFunction::Run() { - scoped_ptr<api_epki::Sign::Params> params( - api_epki::Sign::Params::Create(*args_)); - EXTENSION_FUNCTION_VALIDATE(params); - std::string platform_keys_token_id; - if (!ValidateToken(params->token_id, &platform_keys_token_id)) - return RespondNow(Error(kErrorInvalidToken)); - - chromeos::platform_keys::HashAlgorithm hash_algorithm; - if (params->hash_algorithm_name == "SHA-1") - hash_algorithm = chromeos::platform_keys::HASH_ALGORITHM_SHA1; - else if (params->hash_algorithm_name == "SHA-256") - hash_algorithm = chromeos::platform_keys::HASH_ALGORITHM_SHA256; - else if (params->hash_algorithm_name == "SHA-384") - hash_algorithm = chromeos::platform_keys::HASH_ALGORITHM_SHA384; - else if (params->hash_algorithm_name == "SHA-512") - hash_algorithm = chromeos::platform_keys::HASH_ALGORITHM_SHA512; - else - return RespondNow(Error(kErrorAlgorithmNotSupported)); - - chromeos::PlatformKeysService* service = - chromeos::PlatformKeysServiceFactory::GetForBrowserContext( - browser_context()); - DCHECK(service); - - service->Sign( - platform_keys_token_id, - std::string(params->public_key.begin(), params->public_key.end()), - hash_algorithm, std::string(params->data.begin(), params->data.end()), - extension_id(), - base::Bind(&EnterprisePlatformKeysInternalSignFunction::OnSigned, this)); - return RespondLater(); -} - -void EnterprisePlatformKeysInternalSignFunction::OnSigned( - const std::string& signature, - const std::string& error_message) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); - if (error_message.empty()) { - Respond(ArgumentList(api_epki::Sign::Results::Create( - std::vector<char>(signature.begin(), signature.end())))); - } else { - Respond(Error(error_message)); - } -} - EnterprisePlatformKeysGetCertificatesFunction:: ~EnterprisePlatformKeysGetCertificatesFunction() { } @@ -162,8 +83,8 @@ api_epk::GetCertificates::Params::Create(*args_)); EXTENSION_FUNCTION_VALIDATE(params); std::string platform_keys_token_id; - if (!ValidateToken(params->token_id, &platform_keys_token_id)) - return RespondNow(Error(kErrorInvalidToken)); + if (!platform_keys::ValidateToken(params->token_id, &platform_keys_token_id)) + return RespondNow(Error(platform_keys::kErrorInvalidToken)); chromeos::platform_keys::GetCertificates( platform_keys_token_id, @@ -208,8 +129,8 @@ api_epk::ImportCertificate::Params::Create(*args_)); EXTENSION_FUNCTION_VALIDATE(params); std::string platform_keys_token_id; - if (!ValidateToken(params->token_id, &platform_keys_token_id)) - return RespondNow(Error(kErrorInvalidToken)); + if (!platform_keys::ValidateToken(params->token_id, &platform_keys_token_id)) + return RespondNow(Error(platform_keys::kErrorInvalidToken)); const std::vector<char>& cert_der = params->certificate; scoped_refptr<net::X509Certificate> cert_x509 = @@ -247,8 +168,8 @@ api_epk::RemoveCertificate::Params::Create(*args_)); EXTENSION_FUNCTION_VALIDATE(params); std::string platform_keys_token_id; - if (!ValidateToken(params->token_id, &platform_keys_token_id)) - return RespondNow(Error(kErrorInvalidToken)); + if (!platform_keys::ValidateToken(params->token_id, &platform_keys_token_id)) + return RespondNow(Error(platform_keys::kErrorInvalidToken)); const std::vector<char>& cert_der = params->certificate; scoped_refptr<net::X509Certificate> cert_x509 = @@ -305,7 +226,7 @@ platform_keys_token_ids->begin(); it != platform_keys_token_ids->end(); ++it) { - std::string token_id = PlatformKeysTokenIdToApiId(*it); + std::string token_id = platform_keys::PlatformKeysTokenIdToApiId(*it); if (token_id.empty()) { Respond(Error(kErrorInternal)); return;
diff --git a/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.h b/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.h index 05d9b11..dd889193 100644 --- a/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.h +++ b/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.h
@@ -8,7 +8,6 @@ #include <string> #include <vector> -#include "base/compiler_specific.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "chrome/browser/extensions/chrome_extension_function.h" @@ -35,20 +34,6 @@ ENTERPRISE_PLATFORMKEYSINTERNAL_GENERATEKEY); }; -class EnterprisePlatformKeysInternalSignFunction - : public ChromeUIThreadExtensionFunction { - private: - ~EnterprisePlatformKeysInternalSignFunction() override; - ResponseAction Run() override; - - // Called when the signature was generated. If an error occurred, - // |signature| will be empty and instead |error_message| be set. - void OnSigned(const std::string& signature, const std::string& error_message); - - DECLARE_EXTENSION_FUNCTION("enterprise.platformKeysInternal.sign", - ENTERPRISE_PLATFORMKEYSINTERNAL_SIGN); -}; - class EnterprisePlatformKeysGetCertificatesFunction : public ChromeUIThreadExtensionFunction { private:
diff --git a/chrome/browser/extensions/api/hotword_private/hotword_private_api.cc b/chrome/browser/extensions/api/hotword_private/hotword_private_api.cc index 9977dd8..8c2f956 100644 --- a/chrome/browser/extensions/api/hotword_private/hotword_private_api.cc +++ b/chrome/browser/extensions/api/hotword_private/hotword_private_api.cc
@@ -97,6 +97,10 @@ SignalEvent(api::hotword_private::OnHotwordTriggered::kEventName); } +void HotwordPrivateEventService::OnDeleteSpeakerModel() { + SignalEvent(api::hotword_private::OnDeleteSpeakerModel::kEventName); +} + void HotwordPrivateEventService::SignalEvent(const std::string& event_name) { EventRouter* router = EventRouter::Get(profile_); if (!router || !router->HasEventListener(event_name))
diff --git a/chrome/browser/extensions/api/hotword_private/hotword_private_api.h b/chrome/browser/extensions/api/hotword_private/hotword_private_api.h index 8759a186..a7135dd 100644 --- a/chrome/browser/extensions/api/hotword_private/hotword_private_api.h +++ b/chrome/browser/extensions/api/hotword_private/hotword_private_api.h
@@ -40,6 +40,8 @@ void OnSpeakerModelSaved(); + void OnDeleteSpeakerModel(); + private: friend class BrowserContextKeyedAPIFactory<HotwordPrivateEventService>;
diff --git a/chrome/browser/extensions/api/hotword_private/hotword_private_apitest.cc b/chrome/browser/extensions/api/hotword_private/hotword_private_apitest.cc index b14bded..4973170 100644 --- a/chrome/browser/extensions/api/hotword_private/hotword_private_apitest.cc +++ b/chrome/browser/extensions/api/hotword_private/hotword_private_apitest.cc
@@ -377,6 +377,26 @@ EXPECT_TRUE(listenerNotification.WaitUntilSatisfied()); } +IN_PROC_BROWSER_TEST_F(HotwordPrivateApiTest, OnDeleteSpeakerModel) { + MockWebHistoryService* web_history = new MockWebHistoryService(profile()); + MockAudioHistoryHandler* handler = + new MockAudioHistoryHandler(profile(), web_history); + service()->SetAudioHistoryHandler(handler); + web_history->SetExpectedValue(false); + profile()->GetPrefs()->SetBoolean(prefs::kHotwordAlwaysOnSearchEnabled, true); + + // Trigger the pref registrar. + extensions::HotwordPrivateEventService::GetFactoryInstance(); + ExtensionTestMessageListener listener("ready", false); + ASSERT_TRUE( + LoadExtensionAsComponent(test_data_dir_.AppendASCII( + "onDeleteSpeakerModel"))); + EXPECT_TRUE(listener.WaitUntilSatisfied()); + + ExtensionTestMessageListener listenerNotification("notification", false); + EXPECT_TRUE(listenerNotification.WaitUntilSatisfied()); +} + IN_PROC_BROWSER_TEST_F(HotwordPrivateApiTest, Training) { EXPECT_FALSE(service()->IsTraining());
diff --git a/chrome/browser/extensions/api/identity/identity_api.cc b/chrome/browser/extensions/api/identity/identity_api.cc index 3cd8668..ca52c1a 100644 --- a/chrome/browser/extensions/api/identity/identity_api.cc +++ b/chrome/browser/extensions/api/identity/identity_api.cc
@@ -288,6 +288,7 @@ IdentityGetAuthTokenFunction::IdentityGetAuthTokenFunction() : OAuth2TokenService::Consumer("extensions_identity_api"), + interactive_(false), should_prompt_for_scopes_(false), should_prompt_for_signin_(false) { } @@ -311,12 +312,12 @@ scoped_ptr<identity::GetAuthToken::Params> params( identity::GetAuthToken::Params::Create(*args_)); EXTENSION_FUNCTION_VALIDATE(params.get()); - bool interactive = params->details.get() && + interactive_ = params->details.get() && params->details->interactive.get() && *params->details->interactive; - should_prompt_for_scopes_ = interactive; - should_prompt_for_signin_ = interactive; + should_prompt_for_scopes_ = interactive_; + should_prompt_for_signin_ = interactive_; const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(extension()); @@ -567,8 +568,13 @@ "error", error.ToString()); CompleteMintTokenFlow(); - switch (error.state()) { + case GoogleServiceAuthError::SERVICE_ERROR: + if (interactive_) { + StartSigninFlow(); + return; + } + break; case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS: case GoogleServiceAuthError::ACCOUNT_DELETED: case GoogleServiceAuthError::ACCOUNT_DISABLED: @@ -646,6 +652,16 @@ break; case GaiaWebAuthFlow::SERVICE_AUTH_ERROR: + // If this is really an authentication error and not just a transient + // network error, and this is an interactive request for a signed-in + // user, then we show signin UI instead of failing. + if (service_error.state() != GoogleServiceAuthError::CONNECTION_FAILED && + service_error.state() != + GoogleServiceAuthError::SERVICE_UNAVAILABLE && + interactive_ && HasLoginToken()) { + StartSigninFlow(); + return; + } error = std::string(identity_constants::kAuthFailure) + service_error.ToString(); break;
diff --git a/chrome/browser/extensions/api/identity/identity_api.h b/chrome/browser/extensions/api/identity/identity_api.h index 489029c..c60563a 100644 --- a/chrome/browser/extensions/api/identity/identity_api.h +++ b/chrome/browser/extensions/api/identity/identity_api.h
@@ -280,6 +280,7 @@ std::string GetOAuth2ClientId() const; + bool interactive_; bool should_prompt_for_scopes_; IdentityMintRequestQueue::MintType mint_token_flow_type_; scoped_ptr<OAuth2MintTokenFlow> mint_token_flow_;
diff --git a/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc b/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc index ad32f10..23a0df4 100644 --- a/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc +++ b/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc
@@ -301,9 +301,7 @@ content::BrowserContext* context, const std::string& extension_id, extensions::LaunchType launch_type) const { - extensions::SetLaunchType( - extensions::ExtensionSystem::Get(context)->extension_service(), - extension_id, launch_type); + extensions::SetLaunchType(context, extension_id, launch_type); } GURL ChromeManagementAPIDelegate::GetIconURL(
diff --git a/chrome/browser/extensions/api/management/management_apitest.cc b/chrome/browser/extensions/api/management/management_apitest.cc index 9b0f132..f0ba11c 100644 --- a/chrome/browser/extensions/api/management/management_apitest.cc +++ b/chrome/browser/extensions/api/management/management_apitest.cc
@@ -240,7 +240,8 @@ // Set a pref indicating that the user wants to launch in a regular tab. // This should be ignored, because panel apps always load in a popup. - extensions::SetLaunchType(service, app_id, extensions::LAUNCH_TYPE_REGULAR); + extensions::SetLaunchType(browser()->profile(), app_id, + extensions::LAUNCH_TYPE_REGULAR); // Load the extension again. std::string app_id_new; @@ -299,7 +300,8 @@ ASSERT_FALSE(service->GetExtensionById(app_id, true)); // Set a pref indicating that the user wants to launch in a window. - extensions::SetLaunchType(service, app_id, extensions::LAUNCH_TYPE_WINDOW); + extensions::SetLaunchType(browser()->profile(), app_id, + extensions::LAUNCH_TYPE_WINDOW); std::string app_id_new; LoadAndWaitForLaunch("management/launch_app_tab", &app_id_new);
diff --git a/chrome/browser/extensions/api/networking_private/networking_private_chromeos.cc b/chrome/browser/extensions/api/networking_private/networking_private_chromeos.cc index 38ee102..2bcc246a 100644 --- a/chrome/browser/extensions/api/networking_private/networking_private_chromeos.cc +++ b/chrome/browser/extensions/api/networking_private/networking_private_chromeos.cc
@@ -283,15 +283,13 @@ const std::string& guid, const StringCallback& success_callback, const FailureCallback& failure_callback) { - chromeos::NetworkPortalDetector* detector = - chromeos::NetworkPortalDetector::Get(); - if (!detector) { + if (!chromeos::NetworkPortalDetector::IsInitialized()) { failure_callback.Run(networking_private::kErrorNotReady); return; } chromeos::NetworkPortalDetector::CaptivePortalState state = - detector->GetCaptivePortalState(guid); + chromeos::NetworkPortalDetector::Get()->GetCaptivePortalState(guid); success_callback.Run( chromeos::NetworkPortalDetector::CaptivePortalStatusString(state.status)); }
diff --git a/chrome/browser/extensions/api/networking_private/networking_private_event_router_chromeos.cc b/chrome/browser/extensions/api/networking_private/networking_private_event_router_chromeos.cc index 5694c7e3..b827f16 100644 --- a/chrome/browser/extensions/api/networking_private/networking_private_event_router_chromeos.cc +++ b/chrome/browser/extensions/api/networking_private/networking_private_event_router_chromeos.cc
@@ -132,11 +132,13 @@ if (should_listen && !listening_) { NetworkHandler::Get()->network_state_handler()->AddObserver( this, FROM_HERE); - NetworkPortalDetector::Get()->AddObserver(this); + if (chromeos::NetworkPortalDetector::IsInitialized()) + NetworkPortalDetector::Get()->AddObserver(this); } else if (!should_listen && listening_) { NetworkHandler::Get()->network_state_handler()->RemoveObserver( this, FROM_HERE); - NetworkPortalDetector::Get()->RemoveObserver(this); + if (chromeos::NetworkPortalDetector::IsInitialized()) + NetworkPortalDetector::Get()->RemoveObserver(this); } listening_ = should_listen; }
diff --git a/chrome/browser/extensions/api/networking_private/networking_private_linux.cc b/chrome/browser/extensions/api/networking_private/networking_private_linux.cc index 2bd77f5a..120e400 100644 --- a/chrome/browser/extensions/api/networking_private/networking_private_linux.cc +++ b/chrome/browser/extensions/api/networking_private/networking_private_linux.cc
@@ -303,6 +303,27 @@ success_callback, failure_callback)); } +bool NetworkingPrivateLinux::GetNetworksForScanRequest() { + if (!network_manager_proxy_) { + return false; + } + + scoped_ptr<NetworkMap> network_map(new NetworkMap); + + // Runs GetAllWiFiAccessPoints on the dbus_thread and returns the + // results back to SendNetworkListChangedEvent to fire the event. No + // callbacks are used in this case. + dbus_thread_.task_runner()->PostTaskAndReply( + FROM_HERE, base::Bind(&NetworkingPrivateLinux::GetAllWiFiAccessPoints, + base::Unretained(this), false /* configured_only */, + false /* visible_only */, 0 /* limit */, + base::Unretained(network_map.get())), + base::Bind(&NetworkingPrivateLinux::OnAccessPointsFoundViaScan, + base::Unretained(this), base::Passed(&network_map))); + + return true; +} + // Constructs the network configuration message and connects to the network. // The message is of the form: // { @@ -540,7 +561,7 @@ } bool NetworkingPrivateLinux::RequestScan() { - return true; + return GetNetworksForScanRequest(); } void NetworkingPrivateLinux::AddObserver( @@ -558,12 +579,25 @@ const NetworkListCallback& success_callback, const FailureCallback& failure_callback) { scoped_ptr<base::ListValue> network_list = CopyNetworkMapToList(*network_map); - // Give ownership to the member variable. network_map_.swap(network_map); + SendNetworkListChangedEvent(*network_list); + success_callback.Run(network_list.Pass()); +} + +void NetworkingPrivateLinux::OnAccessPointsFoundViaScan( + scoped_ptr<NetworkMap> network_map) { + scoped_ptr<base::ListValue> network_list = CopyNetworkMapToList(*network_map); + // Give ownership to the member variable. + network_map_.swap(network_map); + SendNetworkListChangedEvent(*network_list); +} + +void NetworkingPrivateLinux::SendNetworkListChangedEvent( + const base::ListValue& network_list) { GuidList guidsForEventCallback; - for (const auto& network : *network_list) { + for (const auto& network : network_list) { std::string guid; base::DictionaryValue* dict; if (network->GetAsDictionary(&dict)) { @@ -573,8 +607,6 @@ } } - // TODO(zentaro): Which order should this be? - success_callback.Run(network_list.Pass()); OnNetworkListChangedEventOnUIThread(guidsForEventCallback); }
diff --git a/chrome/browser/extensions/api/networking_private/networking_private_linux.h b/chrome/browser/extensions/api/networking_private/networking_private_linux.h index 5912f15d..a9497b4 100644 --- a/chrome/browser/extensions/api/networking_private/networking_private_linux.h +++ b/chrome/browser/extensions/api/networking_private/networking_private_linux.h
@@ -123,6 +123,11 @@ int limit, NetworkMap* network_map); + // Helper function for handling a scan request. This function acts similarly + // to the public GetNetworks to get visible networks and fire the + // OnNetworkListChanged event, however no callbacks are called. + bool GetNetworksForScanRequest(); + // Initiates the connection to the network. // Must be called on |dbus_thread_|. void ConnectToNetwork(const std::string& guid, std::string* error); @@ -155,11 +160,20 @@ bool AddAccessPointsFromDevice(const dbus::ObjectPath& device_path, NetworkMap* network_map); - // Reply callback accepts the map of networks and fires the callback. + // Reply callback accepts the map of networks and fires the + // OnNetworkListChanged event and user callbacks. void OnAccessPointsFound(scoped_ptr<NetworkMap> network_map, const NetworkListCallback& success_callback, const FailureCallback& failure_callback); + // Reply callback accepts the map of networks and fires the + // OnNetworkListChanged event. + void OnAccessPointsFoundViaScan(scoped_ptr<NetworkMap> network_map); + + // Helper function for OnAccessPointsFound and OnAccessPointsFoundViaScan to + // fire the OnNetworkListChangedEvent. + void SendNetworkListChangedEvent(const base::ListValue& network_list); + // Gets a dictionary of information about the access point. // Returns false if there is an error getting information about the // supplied |access_point_path|.
diff --git a/chrome/browser/extensions/api/notifications/notifications_api.cc b/chrome/browser/extensions/api/notifications/notifications_api.cc index 3830a7c..6afb8850 100644 --- a/chrome/browser/extensions/api/notifications/notifications_api.cc +++ b/chrome/browser/extensions/api/notifications/notifications_api.cc
@@ -287,7 +287,6 @@ title, message, icon, - blink::WebTextDirectionDefault, message_center::NotifierId( message_center::NotifierId::APPLICATION, extension_->id()),
diff --git a/chrome/browser/extensions/api/page_capture/page_capture_api.h b/chrome/browser/extensions/api/page_capture/page_capture_api.h index 0c1aa1c..ad467bbd 100644 --- a/chrome/browser/extensions/api/page_capture/page_capture_api.h +++ b/chrome/browser/extensions/api/page_capture/page_capture_api.h
@@ -10,7 +10,7 @@ #include "base/memory/ref_counted.h" #include "chrome/browser/extensions/chrome_extension_function.h" #include "chrome/common/extensions/api/page_capture.h" -#include "storage/common/blob/shareable_file_reference.h" +#include "storage/browser/blob/shareable_file_reference.h" namespace base { class FilePath;
diff --git a/chrome/browser/extensions/api/platform_keys/platform_keys_api.cc b/chrome/browser/extensions/api/platform_keys/platform_keys_api.cc new file mode 100644 index 0000000..819558be --- /dev/null +++ b/chrome/browser/extensions/api/platform_keys/platform_keys_api.cc
@@ -0,0 +1,104 @@ +// Copyright 2015 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/extensions/api/platform_keys/platform_keys_api.h" + +#include <vector> + +#include "base/bind.h" +#include "base/logging.h" +#include "chrome/browser/chromeos/platform_keys/platform_keys.h" +#include "chrome/browser/chromeos/platform_keys/platform_keys_service.h" +#include "chrome/browser/chromeos/platform_keys/platform_keys_service_factory.h" +#include "chrome/common/extensions/api/platform_keys_internal.h" +#include "content/public/browser/browser_thread.h" +#include "net/cert/x509_certificate.h" + +namespace extensions { + +namespace api_pki = api::platform_keys_internal; + +namespace platform_keys { + +const char kErrorInvalidToken[] = "The token is not valid."; +const char kErrorAlgorithmNotSupported[] = "Algorithm not supported."; +const char kTokenIdUser[] = "user"; +const char kTokenIdSystem[] = "system"; + +// Returns whether |token_id| references a known Token. +bool ValidateToken(const std::string& token_id, + std::string* platform_keys_token_id) { + platform_keys_token_id->clear(); + if (token_id == kTokenIdUser) { + *platform_keys_token_id = chromeos::platform_keys::kTokenIdUser; + return true; + } + if (token_id == kTokenIdSystem) { + *platform_keys_token_id = chromeos::platform_keys::kTokenIdSystem; + return true; + } + return false; +} + +std::string PlatformKeysTokenIdToApiId( + const std::string& platform_keys_token_id) { + if (platform_keys_token_id == chromeos::platform_keys::kTokenIdUser) + return kTokenIdUser; + if (platform_keys_token_id == chromeos::platform_keys::kTokenIdSystem) + return kTokenIdSystem; + + return std::string(); +} + +} // namespace platform_keys + +PlatformKeysInternalSignFunction::~PlatformKeysInternalSignFunction() { +} + +ExtensionFunction::ResponseAction PlatformKeysInternalSignFunction::Run() { + scoped_ptr<api_pki::Sign::Params> params( + api_pki::Sign::Params::Create(*args_)); + EXTENSION_FUNCTION_VALIDATE(params); + std::string platform_keys_token_id; + if (!platform_keys::ValidateToken(params->token_id, &platform_keys_token_id)) + return RespondNow(Error(platform_keys::kErrorInvalidToken)); + + chromeos::platform_keys::HashAlgorithm hash_algorithm; + if (params->hash_algorithm_name == "SHA-1") + hash_algorithm = chromeos::platform_keys::HASH_ALGORITHM_SHA1; + else if (params->hash_algorithm_name == "SHA-256") + hash_algorithm = chromeos::platform_keys::HASH_ALGORITHM_SHA256; + else if (params->hash_algorithm_name == "SHA-384") + hash_algorithm = chromeos::platform_keys::HASH_ALGORITHM_SHA384; + else if (params->hash_algorithm_name == "SHA-512") + hash_algorithm = chromeos::platform_keys::HASH_ALGORITHM_SHA512; + else + return RespondNow(Error(platform_keys::kErrorAlgorithmNotSupported)); + + chromeos::PlatformKeysService* service = + chromeos::PlatformKeysServiceFactory::GetForBrowserContext( + browser_context()); + DCHECK(service); + + service->Sign( + platform_keys_token_id, + std::string(params->public_key.begin(), params->public_key.end()), + hash_algorithm, std::string(params->data.begin(), params->data.end()), + extension_id(), + base::Bind(&PlatformKeysInternalSignFunction::OnSigned, this)); + return RespondLater(); +} + +void PlatformKeysInternalSignFunction::OnSigned( + const std::string& signature, + const std::string& error_message) { + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + if (error_message.empty()) + Respond(ArgumentList(api_pki::Sign::Results::Create( + std::vector<char>(signature.begin(), signature.end())))); + else + Respond(Error(error_message)); +} + +} // namespace extensions
diff --git a/chrome/browser/extensions/api/platform_keys/platform_keys_api.h b/chrome/browser/extensions/api/platform_keys/platform_keys_api.h new file mode 100644 index 0000000..def650c --- /dev/null +++ b/chrome/browser/extensions/api/platform_keys/platform_keys_api.h
@@ -0,0 +1,44 @@ +// Copyright 2015 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_EXTENSIONS_API_PLATFORM_KEYS_PLATFORM_KEYS_API_H_ +#define CHROME_BROWSER_EXTENSIONS_API_PLATFORM_KEYS_PLATFORM_KEYS_API_H_ + +#include <string> + +#include "chrome/browser/extensions/chrome_extension_function.h" + +namespace extensions { +namespace platform_keys { + +extern const char kErrorInvalidToken[]; + +// Returns whether |token_id| references a known Token. +bool ValidateToken(const std::string& token_id, + std::string* platform_keys_token_id); + +// Converts a token id from ::chromeos::platform_keys to the platformKeys API +// token id. +std::string PlatformKeysTokenIdToApiId( + const std::string& platform_keys_token_id); + +} // namespace platform_keys + +class PlatformKeysInternalSignFunction + : public ChromeUIThreadExtensionFunction { + private: + ~PlatformKeysInternalSignFunction() override; + ResponseAction Run() override; + + // Called when the signature was generated. If an error occurred, + // |signature| will be empty and instead |error_message| be set. + void OnSigned(const std::string& signature, const std::string& error_message); + + DECLARE_EXTENSION_FUNCTION("platformKeysInternal.sign", + PLATFORMKEYSINTERNAL_SIGN); +}; + +} // namespace extensions + +#endif // CHROME_BROWSER_EXTENSIONS_API_PLATFORM_KEYS_PLATFORM_KEYS_API_H_
diff --git a/chrome/browser/extensions/api/web_navigation/web_navigation_api.cc b/chrome/browser/extensions/api/web_navigation/web_navigation_api.cc index 47a7d05..478bb40 100644 --- a/chrome/browser/extensions/api/web_navigation/web_navigation_api.cc +++ b/chrome/browser/extensions/api/web_navigation/web_navigation_api.cc
@@ -324,9 +324,10 @@ } void WebNavigationTabObserver::AboutToNavigateRenderFrame( - content::RenderFrameHost* render_frame_host) { + content::RenderFrameHost* old_host, + content::RenderFrameHost* new_host) { content::RenderViewHost* render_view_host = - render_frame_host->GetRenderViewHost(); + new_host->GetRenderViewHost(); if (!render_view_host_) { render_view_host_ = render_view_host; } else if (render_view_host != render_view_host_) {
diff --git a/chrome/browser/extensions/api/web_navigation/web_navigation_api.h b/chrome/browser/extensions/api/web_navigation/web_navigation_api.h index 3c3d433..9c652735 100644 --- a/chrome/browser/extensions/api/web_navigation/web_navigation_api.h +++ b/chrome/browser/extensions/api/web_navigation/web_navigation_api.h
@@ -55,7 +55,8 @@ void RenderFrameDeleted(content::RenderFrameHost* render_frame_host) override; void RenderViewDeleted(content::RenderViewHost* render_view_host) override; void AboutToNavigateRenderFrame( - content::RenderFrameHost* render_frame_host) override; + content::RenderFrameHost* old_host, + content::RenderFrameHost* new_host) override; void DidStartProvisionalLoadForFrame( content::RenderFrameHost* render_frame_host, const GURL& validated_url,
diff --git a/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc b/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc index c867fab..354763a 100644 --- a/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc +++ b/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc
@@ -223,11 +223,11 @@ base::WeakPtrFactory<TestIPCSender> ipc_sender_factory(&ipc_sender_); ExtensionWebRequestEventRouter::GetInstance()->AddEventListener( &profile_, extension1_id, extension1_id, kEventName, kEventName + "/1", - filter, ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING, -1, -1, + filter, ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING, 0, 0, ipc_sender_factory.GetWeakPtr()); ExtensionWebRequestEventRouter::GetInstance()->AddEventListener( &profile_, extension2_id, extension2_id, kEventName, kEventName + "/2", - filter, ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING, -1, -1, + filter, ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING, 0, 0, ipc_sender_factory.GetWeakPtr()); net::URLRequestJobFactoryImpl job_factory; @@ -359,11 +359,11 @@ base::WeakPtrFactory<TestIPCSender> ipc_sender_factory(&ipc_sender_); ExtensionWebRequestEventRouter::GetInstance()->AddEventListener( &profile_, extension1_id, extension1_id, kEventName, kEventName + "/1", - filter, ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING, -1, -1, + filter, ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING, 0, 0, ipc_sender_factory.GetWeakPtr()); ExtensionWebRequestEventRouter::GetInstance()->AddEventListener( &profile_, extension2_id, extension2_id, kEventName, kEventName + "/2", - filter, ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING, -1, -1, + filter, ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING, 0, 0, ipc_sender_factory.GetWeakPtr()); GURL request_url("about:blank"); @@ -428,11 +428,11 @@ base::WeakPtrFactory<TestIPCSender> ipc_sender_factory(&ipc_sender_); ExtensionWebRequestEventRouter::GetInstance()->AddEventListener( &profile_, extension_id, extension_id, kEventName, kEventName + "/1", - filter, ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING, -1, -1, + filter, ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING, 0, 0, ipc_sender_factory.GetWeakPtr()); ExtensionWebRequestEventRouter::GetInstance()->AddEventListener( &profile_, extension_id, extension_id, kEventName2, kEventName2 + "/1", - filter, 0, -1, -1, ipc_sender_factory.GetWeakPtr()); + filter, 0, 0, 0, ipc_sender_factory.GetWeakPtr()); GURL request_url("about:blank"); scoped_ptr<net::URLRequest> request(context_->CreateRequest( @@ -625,7 +625,7 @@ ASSERT_TRUE(GenerateInfoSpec(string_spec_post, &extra_info_spec_body)); ExtensionWebRequestEventRouter::GetInstance()->AddEventListener( &profile_, extension_id, extension_id, kEventName, kEventName + "/1", - filter, extra_info_spec_body, -1, -1, ipc_sender_factory.GetWeakPtr()); + filter, extra_info_spec_body, 0, 0, ipc_sender_factory.GetWeakPtr()); FireURLRequestWithData(kMethodPost, kMultipart, form_1, form_2); @@ -641,7 +641,7 @@ GenerateInfoSpec(string_spec_no_post, &extra_info_spec_empty)); ExtensionWebRequestEventRouter::GetInstance()->AddEventListener( &profile_, extension_id, extension_id, kEventName, kEventName + "/1", - filter, extra_info_spec_empty, -1, -1, ipc_sender_factory.GetWeakPtr()); + filter, extra_info_spec_empty, 0, 0, ipc_sender_factory.GetWeakPtr()); FireURLRequestWithData(kMethodPost, kMultipart, form_1, form_2); @@ -651,7 +651,7 @@ // Subscribe to OnBeforeRequest with requestBody requirement. ExtensionWebRequestEventRouter::GetInstance()->AddEventListener( &profile_, extension_id, extension_id, kEventName, kEventName + "/1", - filter, extra_info_spec_body, -1, -1, ipc_sender_factory.GetWeakPtr()); + filter, extra_info_spec_body, 0, 0, ipc_sender_factory.GetWeakPtr()); // Part 3. // Now send a POST request with body which is not parseable as a form. @@ -709,7 +709,7 @@ // Subscribe to OnBeforeRequest with requestBody requirement. ExtensionWebRequestEventRouter::GetInstance()->AddEventListener( &profile_, extension_id, extension_id, kEventName, kEventName + "/1", - filter, extra_info_spec, -1, -1, ipc_sender_factory.GetWeakPtr()); + filter, extra_info_spec, 0, 0, ipc_sender_factory.GetWeakPtr()); // The request URL can be arbitrary but must have an HTTP or HTTPS scheme. const GURL request_url("http://www.example.com"); @@ -821,18 +821,18 @@ // higher precedence than extension 1. ExtensionWebRequestEventRouter::GetInstance()->AddEventListener( &profile_, extension1_id, extension1_id, kEventName, kEventName + "/1", - filter, ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING, -1, -1, + filter, ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING, 0, 0, ipc_sender_factory.GetWeakPtr()); ExtensionWebRequestEventRouter::GetInstance()->AddEventListener( &profile_, extension2_id, extension2_id, kEventName, kEventName + "/2", - filter, ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING, -1, -1, + filter, ExtensionWebRequestEventRouter::ExtraInfoSpec::BLOCKING, 0, 0, ipc_sender_factory.GetWeakPtr()); // Install one extension that observes the final headers. ExtensionWebRequestEventRouter::GetInstance()->AddEventListener( &profile_, extension3_id, extension3_id, keys::kOnSendHeadersEvent, std::string(keys::kOnSendHeadersEvent) + "/3", filter, - ExtensionWebRequestEventRouter::ExtraInfoSpec::REQUEST_HEADERS, -1, -1, + ExtensionWebRequestEventRouter::ExtraInfoSpec::REQUEST_HEADERS, 0, 0, ipc_sender_factory.GetWeakPtr()); GURL request_url("http://doesnotexist/does_not_exist.html");
diff --git a/chrome/browser/extensions/component_loader.cc b/chrome/browser/extensions/component_loader.cc index f83cd7b..53309b2 100644 --- a/chrome/browser/extensions/component_loader.cc +++ b/chrome/browser/extensions/component_loader.cc
@@ -91,6 +91,7 @@ bool IsNormalSession() { return !base::CommandLine::ForCurrentProcess()->HasSwitch( chromeos::switches::kGuestSession) && + user_manager::UserManager::IsInitialized() && user_manager::UserManager::Get()->IsUserLoggedIn(); } #endif // defined(OS_CHROMEOS)
diff --git a/chrome/browser/extensions/extension_sync_service.cc b/chrome/browser/extensions/extension_sync_service.cc index cd8d3aa..ccb04ecf 100644 --- a/chrome/browser/extensions/extension_sync_service.cc +++ b/chrome/browser/extensions/extension_sync_service.cc
@@ -88,8 +88,9 @@ ExtensionSyncService::~ExtensionSyncService() {} // static -ExtensionSyncService* ExtensionSyncService::Get(Profile* profile) { - return ExtensionSyncServiceFactory::GetForProfile(profile); +ExtensionSyncService* ExtensionSyncService::Get( + content::BrowserContext* context) { + return ExtensionSyncServiceFactory::GetForBrowserContext(context); } syncer::SyncChange ExtensionSyncService::PrepareToSyncUninstallExtension( @@ -346,8 +347,7 @@ // is in AppSyncData::PopulateAppSpecifics. if (app_sync_data.launch_type() >= extensions::LAUNCH_TYPE_FIRST && app_sync_data.launch_type() < extensions::NUM_LAUNCH_TYPES) { - extensions::SetLaunchType(extension_service_, id, - app_sync_data.launch_type()); + extensions::SetLaunchType(profile_, id, app_sync_data.launch_type()); } if (!app_sync_data.bookmark_app_url().empty())
diff --git a/chrome/browser/extensions/extension_sync_service.h b/chrome/browser/extensions/extension_sync_service.h index 0b359d7c9..9efb52d 100644 --- a/chrome/browser/extensions/extension_sync_service.h +++ b/chrome/browser/extensions/extension_sync_service.h
@@ -45,8 +45,8 @@ ~ExtensionSyncService() override; - // Convenience function to get the ExtensionSyncService for a Profile. - static ExtensionSyncService* Get(Profile* profile); + // Convenience function to get the ExtensionSyncService for a BrowserContext. + static ExtensionSyncService* Get(content::BrowserContext* context); const extensions::ExtensionPrefs& extension_prefs() const { return *extension_prefs_;
diff --git a/chrome/browser/extensions/extension_sync_service_factory.cc b/chrome/browser/extensions/extension_sync_service_factory.cc index 23b0c132..ea97ca37 100644 --- a/chrome/browser/extensions/extension_sync_service_factory.cc +++ b/chrome/browser/extensions/extension_sync_service_factory.cc
@@ -14,10 +14,10 @@ #include "extensions/browser/extensions_browser_client.h" // static -ExtensionSyncService* ExtensionSyncServiceFactory::GetForProfile( - Profile* profile) { +ExtensionSyncService* ExtensionSyncServiceFactory::GetForBrowserContext( + content::BrowserContext* context) { return static_cast<ExtensionSyncService*>( - GetInstance()->GetServiceForBrowserContext(profile, true)); + GetInstance()->GetServiceForBrowserContext(context, true)); } // static
diff --git a/chrome/browser/extensions/extension_sync_service_factory.h b/chrome/browser/extensions/extension_sync_service_factory.h index 2edba18..82a36d2 100644 --- a/chrome/browser/extensions/extension_sync_service_factory.h +++ b/chrome/browser/extensions/extension_sync_service_factory.h
@@ -10,11 +10,11 @@ #include "components/keyed_service/content/browser_context_keyed_service_factory.h" class ExtensionSyncService; -class Profile; class ExtensionSyncServiceFactory : public BrowserContextKeyedServiceFactory { public: - static ExtensionSyncService* GetForProfile(Profile* profile); + static ExtensionSyncService* GetForBrowserContext( + content::BrowserContext* context); static ExtensionSyncServiceFactory* GetInstance(); @@ -25,7 +25,7 @@ ~ExtensionSyncServiceFactory() override; KeyedService* BuildServiceInstanceFor( - content::BrowserContext* profile) const override; + content::BrowserContext* context) const override; content::BrowserContext* GetBrowserContextToUse( content::BrowserContext* context) const override; };
diff --git a/chrome/browser/extensions/launch_util.cc b/chrome/browser/extensions/launch_util.cc index 82b75dc4..37faf2a 100644 --- a/chrome/browser/extensions/launch_util.cc +++ b/chrome/browser/extensions/launch_util.cc
@@ -5,7 +5,6 @@ #include "chrome/browser/extensions/launch_util.h" #include "base/values.h" -#include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/extension_sync_service.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/host_desktop.h" @@ -13,6 +12,7 @@ #include "chrome/common/extensions/manifest_handlers/app_launch_info.h" #include "components/pref_registry/pref_registry_syncable.h" #include "extensions/browser/extension_prefs.h" +#include "extensions/browser/extension_registry.h" #include "extensions/browser/pref_names.h" #include "extensions/common/extension.h" @@ -35,7 +35,7 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) { registry->RegisterIntegerPref( pref_names::kBookmarkAppCreationLaunchType, - LAUNCH_TYPE_WINDOW, + LAUNCH_TYPE_REGULAR, user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); } @@ -59,22 +59,21 @@ ? static_cast<LaunchType>(value) : LAUNCH_TYPE_INVALID; } -void SetLaunchType(ExtensionService* service, +void SetLaunchType(content::BrowserContext* context, const std::string& extension_id, LaunchType launch_type) { DCHECK(launch_type >= LAUNCH_TYPE_FIRST && launch_type < NUM_LAUNCH_TYPES); - ExtensionPrefs::Get(service->profile())->UpdateExtensionPref( - extension_id, - kPrefLaunchType, + ExtensionPrefs::Get(context)->UpdateExtensionPref( + extension_id, kPrefLaunchType, new base::FundamentalValue(static_cast<int>(launch_type))); // Sync the launch type. - const Extension* extension = service->GetInstalledExtension(extension_id); - if (extension) { - ExtensionSyncService::Get(service->profile())-> - SyncExtensionChangeIfNeeded(*extension); - } + const Extension* extension = + ExtensionRegistry::Get(context) + ->GetExtensionById(extension_id, ExtensionRegistry::EVERYTHING); + if (extension) + ExtensionSyncService::Get(context)->SyncExtensionChangeIfNeeded(*extension); } LaunchContainer GetLaunchContainer(const ExtensionPrefs* prefs,
diff --git a/chrome/browser/extensions/launch_util.h b/chrome/browser/extensions/launch_util.h index 3cf2641..9b0b294 100644 --- a/chrome/browser/extensions/launch_util.h +++ b/chrome/browser/extensions/launch_util.h
@@ -9,7 +9,9 @@ #include "extensions/common/constants.h" -class ExtensionService; +namespace content { +class BrowserContext; +} namespace user_prefs { class PrefRegistrySyncable; @@ -38,7 +40,7 @@ const std::string& extension_id); // Sets an extension's launch type preference and syncs the value if necessary. -void SetLaunchType(ExtensionService* prefs, +void SetLaunchType(content::BrowserContext* context, const std::string& extension_id, LaunchType launch_type);
diff --git a/chrome/browser/extensions/state_store_notification_observer.cc b/chrome/browser/extensions/state_store_notification_observer.cc index 0e5084c..3865fb4 100644 --- a/chrome/browser/extensions/state_store_notification_observer.cc +++ b/chrome/browser/extensions/state_store_notification_observer.cc
@@ -14,20 +14,17 @@ StateStoreNotificationObserver::StateStoreNotificationObserver( StateStore* state_store) : state_store_(state_store) { - registrar_.Add(this, - chrome::NOTIFICATION_SESSION_RESTORE_DONE, - content::NotificationService::AllBrowserContextsAndSources()); + on_session_restored_callback_subscription_ = + SessionRestore::RegisterOnSessionRestoredCallback( + base::Bind(&StateStoreNotificationObserver::OnSessionRestoreDone, + base::Unretained(this))); } StateStoreNotificationObserver::~StateStoreNotificationObserver() { } -void StateStoreNotificationObserver::Observe( - int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) { - DCHECK_EQ(type, chrome::NOTIFICATION_SESSION_RESTORE_DONE); - registrar_.RemoveAll(); +void StateStoreNotificationObserver::OnSessionRestoreDone() { + on_session_restored_callback_subscription_.reset(); state_store_->RequestInitAfterDelay(); }
diff --git a/chrome/browser/extensions/state_store_notification_observer.h b/chrome/browser/extensions/state_store_notification_observer.h index fd24d59..63f45a6e 100644 --- a/chrome/browser/extensions/state_store_notification_observer.h +++ b/chrome/browser/extensions/state_store_notification_observer.h
@@ -7,8 +7,7 @@ #include "base/compiler_specific.h" #include "base/macros.h" -#include "content/public/browser/notification_observer.h" -#include "content/public/browser/notification_registrar.h" +#include "chrome/browser/sessions/session_restore.h" namespace extensions { class StateStore; @@ -16,19 +15,24 @@ // Initializes the StateStore when session restore is complete, for example when // page load notifications are not sent ("Continue where I left off"). // http://crbug.com/230481 -class StateStoreNotificationObserver : public content::NotificationObserver { +class StateStoreNotificationObserver { public: explicit StateStoreNotificationObserver(StateStore* state_store); - ~StateStoreNotificationObserver() override; - - // content::NotificationObserver overrides: - void Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) override; + ~StateStoreNotificationObserver(); private: + // Called when a session restore has finished. + void OnSessionRestoreDone(); + StateStore* state_store_; // Not owned. - content::NotificationRegistrar registrar_; + + // Points to the on-session-restored callback that was registered with + // SessionRestore's callback list. When objects of this class are destroyed, + // the subscription object's destructor will automatically unregister the + // callback in SessionRestore, so that the callback list does not contain any + // obsolete callbacks. + SessionRestore::CallbackSubscription + on_session_restored_callback_subscription_; DISALLOW_COPY_AND_ASSIGN(StateStoreNotificationObserver); };
diff --git a/chrome/browser/google/google_update_win.cc b/chrome/browser/google/google_update_win.cc index f15b7a34..791279a 100644 --- a/chrome/browser/google/google_update_win.cc +++ b/chrome/browser/google/google_update_win.cc
@@ -91,7 +91,10 @@ base::StringPrintf(L"Elevation:Administrator!new:%ls", class_id_as_string); - BIND_OPTS3 bind_opts = {}; + BIND_OPTS3 bind_opts; + // An explicit memset is needed rather than relying on value initialization + // since BIND_OPTS3 is not an aggregate (it is a derived type). + memset(&bind_opts, 0, sizeof(bind_opts)); bind_opts.cbStruct = sizeof(bind_opts); bind_opts.dwClassContext = CLSCTX_LOCAL_SERVER; bind_opts.hwnd = hwnd;
diff --git a/chrome/browser/history/android/android_provider_backend_unittest.cc b/chrome/browser/history/android/android_provider_backend_unittest.cc index 76be6fdb..59e189e 100644 --- a/chrome/browser/history/android/android_provider_backend_unittest.cc +++ b/chrome/browser/history/android/android_provider_backend_unittest.cc
@@ -90,6 +90,7 @@ void NotifyKeywordSearchTermUpdated(const URLRow& row, KeywordID keyword_id, const base::string16& term) override {} + void NotifyKeywordSearchTermDeleted(URLID url_id) override {} void BroadcastNotifications( int type, scoped_ptr<HistoryDetails> details) override {
diff --git a/chrome/browser/history/expire_history_backend_unittest.cc b/chrome/browser/history/expire_history_backend_unittest.cc index c63b465..d5e1981 100644 --- a/chrome/browser/history/expire_history_backend_unittest.cc +++ b/chrome/browser/history/expire_history_backend_unittest.cc
@@ -12,14 +12,12 @@ #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/memory/scoped_ptr.h" -#include "base/stl_util.h" #include "base/strings/string16.h" #include "base/strings/utf_string_conversions.h" -#include "chrome/browser/history/expire_history_backend.h" -#include "chrome/browser/history/history_details.h" #include "chrome/browser/history/top_sites.h" #include "chrome/test/base/testing_profile.h" #include "chrome/tools/profiles/thumbnail-inl.h" +#include "components/history/core/browser/expire_history_backend.h" #include "components/history/core/browser/history_backend_notifier.h" #include "components/history/core/browser/history_database.h" #include "components/history/core/browser/thumbnail_database.h" @@ -63,7 +61,7 @@ // Add visits with source information. void AddExampleSourceData(const GURL& url, URLID* id); - // Returns true if the given favicon/thumanil has an entry in the DB. + // Returns true if the given favicon/thumbnail has an entry in the DB. bool HasFavicon(favicon_base::FaviconID favicon_id); bool HasThumbnail(URLID url_id); @@ -81,7 +79,6 @@ // Clears the list of notifications received. void ClearLastNotifications() { - STLDeleteValues(¬ifications_); urls_modified_notifications_.clear(); urls_deleted_notifications_.clear(); } @@ -112,13 +109,7 @@ // Time at the beginning of the test, so everybody agrees what "now" is. const Time now_; - // Notifications intended to be broadcast, we can check these values to make - // sure that the deletor is doing the correct broadcasts. We own the details - // pointers. - typedef std::vector< std::pair<int, HistoryDetails*> > - NotificationList; - NotificationList notifications_; - + // Details received from HistoryObserver events. typedef std::vector<URLRows> URLsModifiedNotificationList; URLsModifiedNotificationList urls_modified_notifications_;
diff --git a/chrome/browser/history/history_backend.cc b/chrome/browser/history/history_backend.cc index 0dd1007..9e1a584 100644 --- a/chrome/browser/history/history_backend.cc +++ b/chrome/browser/history/history_backend.cc
@@ -1086,9 +1086,9 @@ return; db_->DeleteKeywordSearchTermForURL(url_id); - BroadcastNotifications( - chrome::NOTIFICATION_HISTORY_KEYWORD_SEARCH_TERM_DELETED, - scoped_ptr<HistoryDetails>(new KeywordSearchDeletedDetails(url_id))); + if (delegate_) + delegate_->NotifyKeywordSearchTermDeleted(url_id); + ScheduleCommit(); }
diff --git a/chrome/browser/history/history_backend.h b/chrome/browser/history/history_backend.h index b4984d3..ee51160a 100644 --- a/chrome/browser/history/history_backend.h +++ b/chrome/browser/history/history_backend.h
@@ -18,7 +18,7 @@ #include "base/observer_list.h" #include "base/single_thread_task_runner.h" #include "base/task/cancelable_task_tracker.h" -#include "chrome/browser/history/expire_history_backend.h" +#include "components/history/core/browser/expire_history_backend.h" #include "components/history/core/browser/history_backend_notifier.h" #include "components/history/core/browser/history_types.h" #include "components/history/core/browser/keyword_id.h" @@ -151,6 +151,11 @@ KeywordID keyword_id, const base::string16& term) = 0; + // Notify HistoryService that keyword search term has been deleted. + // The event will be forwarded to the HistoryServiceObservers in the correct + // thread. + virtual void NotifyKeywordSearchTermDeleted(URLID url_id) = 0; + // Broadcasts the specified notification to the notification service. // This is implemented here because notifications must only be sent from // the main thread. This is the only method that doesn't identify the
diff --git a/chrome/browser/history/history_backend_unittest.cc b/chrome/browser/history/history_backend_unittest.cc index 85231b6..21d67c0 100644 --- a/chrome/browser/history/history_backend_unittest.cc +++ b/chrome/browser/history/history_backend_unittest.cc
@@ -131,6 +131,7 @@ void NotifyKeywordSearchTermUpdated(const URLRow& row, KeywordID keyword_id, const base::string16& term) override; + void NotifyKeywordSearchTermDeleted(URLID url_id) override; void BroadcastNotifications(int type, scoped_ptr<HistoryDetails> details) override; void DBLoaded() override; @@ -225,6 +226,10 @@ mem_backend_->OnKeywordSearchTermUpdated(nullptr, row, keyword_id, term); } + void NotifyKeywordSearchTermDeleted(URLID url_id) { + mem_backend_->OnKeywordSearchTermDeleted(nullptr, url_id); + } + void BroadcastNotifications(int type, scoped_ptr<HistoryDetails> details) { // Send the notifications directly to the in-memory database. content::Details<HistoryDetails> det(details.get()); @@ -312,6 +317,10 @@ test_->NotifyKeywordSearchTermUpdated(row, keyword_id, term); } +void HistoryBackendTestDelegate::NotifyKeywordSearchTermDeleted(URLID url_id) { + test_->NotifyKeywordSearchTermDeleted(url_id); +} + void HistoryBackendTestDelegate::BroadcastNotifications( int type, scoped_ptr<HistoryDetails> details) {
diff --git a/chrome/browser/history/history_notifications.cc b/chrome/browser/history/history_notifications.cc index e052ec6..47efa27 100644 --- a/chrome/browser/history/history_notifications.cc +++ b/chrome/browser/history/history_notifications.cc
@@ -17,10 +17,4 @@ URLsDeletedDetails::~URLsDeletedDetails() {} -KeywordSearchDeletedDetails::KeywordSearchDeletedDetails(URLID url_row_id) - : url_row_id(url_row_id) { -} - -KeywordSearchDeletedDetails::~KeywordSearchDeletedDetails() {} - } // namespace history
diff --git a/chrome/browser/history/history_notifications.h b/chrome/browser/history/history_notifications.h index 84c3720e..564ee90 100644 --- a/chrome/browser/history/history_notifications.h +++ b/chrome/browser/history/history_notifications.h
@@ -48,15 +48,6 @@ std::set<GURL> favicon_urls; }; -// Details for HISTORY_KEYWORD_SEARCH_TERM_DELETED. -struct KeywordSearchDeletedDetails : public HistoryDetails { - explicit KeywordSearchDeletedDetails(URLID url_row_id); - ~KeywordSearchDeletedDetails() override; - - // The ID of the corresponding URLRow in the main history database. - URLID url_row_id; -}; - } // namespace history #endif // CHROME_BROWSER_HISTORY_HISTORY_NOTIFICATIONS_H__
diff --git a/chrome/browser/history/history_service.cc b/chrome/browser/history/history_service.cc index b59a623..5e830ec 100644 --- a/chrome/browser/history/history_service.cc +++ b/chrome/browser/history/history_service.cc
@@ -198,6 +198,12 @@ history_service_, row, keyword_id, term)); } + void NotifyKeywordSearchTermDeleted(history::URLID url_id) override { + service_task_runner_->PostTask( + FROM_HERE, base::Bind(&HistoryService::NotifyKeywordSearchTermDeleted, + history_service_, url_id)); + } + void BroadcastNotifications( int type, scoped_ptr<history::HistoryDetails> details) override { @@ -1302,6 +1308,12 @@ OnKeywordSearchTermUpdated(this, row, keyword_id, term)); } +void HistoryService::NotifyKeywordSearchTermDeleted(history::URLID url_id) { + DCHECK(thread_checker_.CalledOnValidThread()); + FOR_EACH_OBSERVER(history::HistoryServiceObserver, observers_, + OnKeywordSearchTermDeleted(this, url_id)); +} + scoped_ptr<base::CallbackList<void(const std::set<GURL>&)>::Subscription> HistoryService::AddFaviconChangedCallback( const HistoryService::OnFaviconChangedCallback& callback) {
diff --git a/chrome/browser/history/history_service.h b/chrome/browser/history/history_service.h index 0501f9b..4ea16f67 100644 --- a/chrome/browser/history/history_service.h +++ b/chrome/browser/history/history_service.h
@@ -625,6 +625,10 @@ history::KeywordID keyword_id, const base::string16& term); + // Notify all HistoryServiceObservers registered that keyword search term is + // deleted. |url_id| is the id of the url row. + void NotifyKeywordSearchTermDeleted(history::URLID url_id); + // Favicon ------------------------------------------------------------------- // These favicon methods are exposed to the FaviconService. Instead of calling
diff --git a/chrome/browser/history/history_unittest.cc b/chrome/browser/history/history_unittest.cc index 885884f..e30a9b87 100644 --- a/chrome/browser/history/history_unittest.cc +++ b/chrome/browser/history/history_unittest.cc
@@ -111,6 +111,7 @@ void NotifyKeywordSearchTermUpdated(const URLRow& row, KeywordID keyword_id, const base::string16& term) override {} + void NotifyKeywordSearchTermDeleted(URLID url_id) override {} void BroadcastNotifications(int type, scoped_ptr<HistoryDetails> details) override; void DBLoaded() override {}
diff --git a/chrome/browser/history/in_memory_history_backend.cc b/chrome/browser/history/in_memory_history_backend.cc index 5076f24c..1165d23 100644 --- a/chrome/browser/history/in_memory_history_backend.cc +++ b/chrome/browser/history/in_memory_history_backend.cc
@@ -60,8 +60,6 @@ // We only want notifications for the associated profile. content::Source<Profile> source(profile_); registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URLS_DELETED, source); - registrar_.Add( - this, chrome::NOTIFICATION_HISTORY_KEYWORD_SEARCH_TERM_DELETED, source); } void InMemoryHistoryBackend::DeleteAllSearchTermsForKeyword( @@ -96,15 +94,19 @@ db_->SetKeywordSearchTermsForURL(row.id(), keyword_id, term); } +void InMemoryHistoryBackend::OnKeywordSearchTermDeleted( + HistoryService* history_service, + URLID url_id) { + // For simplicity, this will not remove the corresponding URLRow, but this is + // okay, as the main database does not do so either. + db_->DeleteKeywordSearchTermForURL(url_id); +} + void InMemoryHistoryBackend::Observe( int type, const content::NotificationSource& source, const content::NotificationDetails& details) { switch (type) { - case chrome::NOTIFICATION_HISTORY_KEYWORD_SEARCH_TERM_DELETED: - OnKeywordSearchTermDeleted( - *content::Details<KeywordSearchDeletedDetails>(details).ptr()); - break; case chrome::NOTIFICATION_HISTORY_URLS_DELETED: OnURLsDeleted(*content::Details<URLsDeletedDetails>(details).ptr()); break; @@ -145,11 +147,4 @@ } } -void InMemoryHistoryBackend::OnKeywordSearchTermDeleted( - const KeywordSearchDeletedDetails& details) { - // For simplicity, this will not remove the corresponding URLRow, but this is - // okay, as the main database does not do so either. - db_->DeleteKeywordSearchTermForURL(details.url_row_id); -} - } // namespace history
diff --git a/chrome/browser/history/in_memory_history_backend.h b/chrome/browser/history/in_memory_history_backend.h index 760d927..2799984 100644 --- a/chrome/browser/history/in_memory_history_backend.h +++ b/chrome/browser/history/in_memory_history_backend.h
@@ -41,7 +41,6 @@ namespace history { class InMemoryDatabase; -struct KeywordSearchDeletedDetails; class URLDatabase; class URLRow; struct URLsDeletedDetails; @@ -85,6 +84,8 @@ const URLRow& row, KeywordID keyword_id, const base::string16& term) override; + void OnKeywordSearchTermDeleted(HistoryService* history_service, + URLID url_id) override; // Notification callback. void Observe(int type, @@ -100,9 +101,6 @@ // Handler for HISTORY_URLS_DELETED. void OnURLsDeleted(const URLsDeletedDetails& details); - // Handler for HISTORY_KEYWORD_SEARCH_TERM_DELETED. - void OnKeywordSearchTermDeleted(const KeywordSearchDeletedDetails& details); - content::NotificationRegistrar registrar_; scoped_ptr<InMemoryDatabase> db_;
diff --git a/chrome/browser/interstitials/security_interstitial_page.cc b/chrome/browser/interstitials/security_interstitial_page.cc index 51321963..dbc248a 100644 --- a/chrome/browser/interstitials/security_interstitial_page.cc +++ b/chrome/browser/interstitials/security_interstitial_page.cc
@@ -64,8 +64,9 @@ base::DictionaryValue load_time_data; PopulateInterstitialStrings(&load_time_data); webui::SetFontAndTextDirection(&load_time_data); - base::StringPiece html( - ResourceBundle::GetSharedInstance().GetRawDataResource( - IDR_SECURITY_INTERSTITIAL_HTML)); + std::string html = ResourceBundle::GetSharedInstance() + .GetRawDataResource(IDR_SECURITY_INTERSTITIAL_HTML) + .as_string(); + webui::AppendWebUiCssTextDefaults(&html); return webui::GetI18nTemplateHtml(html, &load_time_data); }
diff --git a/chrome/browser/io_thread.cc b/chrome/browser/io_thread.cc index 6e055650..efa8f53 100644 --- a/chrome/browser/io_thread.cc +++ b/chrome/browser/io_thread.cc
@@ -35,18 +35,11 @@ #include "chrome/browser/net/dns_probe_service.h" #include "chrome/browser/net/pref_proxy_config_tracker.h" #include "chrome/browser/net/proxy_service_factory.h" -#include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings.h" -#include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings_factory.h" #include "chrome/common/chrome_content_client.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/chrome_version_info.h" #include "chrome/common/pref_names.h" -#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_auth_request_handler.h" -#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.h" -#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_prefs.h" -#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h" -#include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h" #include "components/policy/core/common/policy_service.h" #include "components/variations/variations_associated_data.h" #include "content/public/browser/browser_thread.h" @@ -601,19 +594,7 @@ chrome_network_delegate->NeverThrottleRequests(); #endif - SetupDataReductionProxy(); - - // This is the same as in ProfileImplIOData except that it does not collect - // usage stats. - data_reduction_proxy::DataReductionProxyNetworkDelegate* network_delegate = - new data_reduction_proxy::DataReductionProxyNetworkDelegate( - chrome_network_delegate.Pass(), - globals_->data_reduction_proxy_params.get(), - globals_->data_reduction_proxy_auth_request_handler.get(), - data_reduction_proxy::DataReductionProxyNetworkDelegate:: - ProxyConfigGetter()); - - globals_->system_network_delegate.reset(network_delegate); + globals_->system_network_delegate = chrome_network_delegate.Pass(); globals_->host_resolver = CreateGlobalHostResolver(net_log_); UpdateDnsClientEnabled(); #if defined(OS_CHROMEOS) @@ -1053,8 +1034,6 @@ ¶ms->quic_disable_connection_pooling); globals.quic_load_server_info_timeout_ms.CopyToIfSet( ¶ms->quic_load_server_info_timeout_ms); - globals.quic_disable_loading_server_info_for_new_servers.CopyToIfSet( - ¶ms->quic_disable_loading_server_info_for_new_servers); globals.quic_load_server_info_timeout_srtt_multiplier.CopyToIfSet( ¶ms->quic_load_server_info_timeout_srtt_multiplier); globals.quic_enable_truncated_connection_ids.CopyToIfSet( @@ -1071,7 +1050,6 @@ ¶ms->origin_to_force_quic_on); params->enable_user_alternate_protocol_ports = globals.enable_user_alternate_protocol_ports; - params->proxy_delegate = globals.data_reduction_proxy_delegate.get(); } base::TimeTicks IOThread::creation_time() const { @@ -1125,7 +1103,6 @@ system_proxy_config_service_.release(), command_line, quick_check_enabled_.GetValue())); - DCHECK(globals_->data_reduction_proxy_params); net::HttpNetworkSession::Params system_params; InitializeNetworkSessionParams(&system_params); @@ -1163,41 +1140,6 @@ ConfigureQuicGlobals(command_line, group, params, globals_); } -void IOThread::SetupDataReductionProxy() { - // TODO(kundaji): Move flags initialization to DataReductionProxyParams and - // merge with flag initialization in - // data_reduction_proxy_chrome_settings_factory.cc. - int flags = data_reduction_proxy::DataReductionProxyParams::kAllowed | - data_reduction_proxy::DataReductionProxyParams::kFallbackAllowed | - data_reduction_proxy::DataReductionProxyParams::kAlternativeAllowed; - if (data_reduction_proxy::DataReductionProxyParams:: - IsIncludedInPromoFieldTrial()) { - flags |= data_reduction_proxy::DataReductionProxyParams::kPromoAllowed; - } - if (data_reduction_proxy::DataReductionProxyParams:: - IsIncludedInHoldbackFieldTrial()) { - flags |= data_reduction_proxy::DataReductionProxyParams::kHoldback; - } -#if defined(OS_ANDROID) - if (data_reduction_proxy::DataReductionProxyParams:: - IsIncludedInAndroidOnePromoFieldTrial( - base::android::BuildInfo::GetInstance()->android_build_fp())) { - flags |= data_reduction_proxy::DataReductionProxyParams::kPromoAllowed; - } -#endif - globals_->data_reduction_proxy_params.reset( - new data_reduction_proxy::DataReductionProxyParams(flags)); - globals_->data_reduction_proxy_auth_request_handler.reset( - new data_reduction_proxy::DataReductionProxyAuthRequestHandler( - DataReductionProxyChromeSettings::GetClient(), - globals_->data_reduction_proxy_params.get(), - BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO))); - globals_->data_reduction_proxy_delegate.reset( - new data_reduction_proxy::DataReductionProxyDelegate( - globals_->data_reduction_proxy_auth_request_handler.get(), - globals_->data_reduction_proxy_params.get())); -} - // static void IOThread::ConfigureQuicGlobals( const base::CommandLine& command_line, @@ -1217,8 +1159,6 @@ globals->quic_load_server_info_timeout_ms.set( load_server_info_timeout_ms); } - globals->quic_disable_loading_server_info_for_new_servers.set( - ShouldDisableLoadingServerInfoForNewServers(quic_trial_params)); float load_server_info_timeout_srtt_multiplier = GetQuicLoadServerInfoTimeoutSrttMultiplier(quic_trial_params); globals->quic_enable_truncated_connection_ids.set( @@ -1385,15 +1325,6 @@ } // static -bool IOThread::ShouldDisableLoadingServerInfoForNewServers( - const VariationParameters& quic_trial_params) { - return LowerCaseEqualsASCII( - GetVariationParam(quic_trial_params, - "disable_loading_server_info_for_new_servers"), - "true"); -} - -// static float IOThread::GetQuicLoadServerInfoTimeoutSrttMultiplier( const VariationParameters& quic_trial_params) { double value;
diff --git a/chrome/browser/io_thread.h b/chrome/browser/io_thread.h index d487b50..1f969ec 100644 --- a/chrome/browser/io_thread.h +++ b/chrome/browser/io_thread.h
@@ -38,12 +38,6 @@ class DnsProbeService; } -namespace data_reduction_proxy { -class DataReductionProxyAuthRequestHandler; -class DataReductionProxyDelegate; -class DataReductionProxyParams; -} - namespace extensions { class EventRouterForwarder; } @@ -192,7 +186,6 @@ Optional<bool> quic_always_require_handshake_confirmation; Optional<bool> quic_disable_connection_pooling; Optional<int> quic_load_server_info_timeout_ms; - Optional<bool> quic_disable_loading_server_info_for_new_servers; Optional<float> quic_load_server_info_timeout_srtt_multiplier; Optional<bool> quic_enable_truncated_connection_ids; Optional<size_t> quic_max_packet_length; @@ -205,12 +198,6 @@ // main frame load fails with a DNS error in order to provide more useful // information to the renderer so it can show a more specific error page. scoped_ptr<chrome_browser_net::DnsProbeService> dns_probe_service; - scoped_ptr<data_reduction_proxy::DataReductionProxyParams> - data_reduction_proxy_params; - scoped_ptr<data_reduction_proxy::DataReductionProxyAuthRequestHandler> - data_reduction_proxy_auth_request_handler; - scoped_ptr<data_reduction_proxy::DataReductionProxyDelegate> - data_reduction_proxy_delegate; }; // |net_log| must either outlive the IOThread or be NULL. @@ -321,9 +308,6 @@ // well as the QUIC field trial group. void ConfigureQuic(const base::CommandLine& command_line); - // Set up data reduction proxy related objects on IO thread globals. - void SetupDataReductionProxy(); - extensions::EventRouterForwarder* extension_event_router_forwarder() { #if defined(ENABLE_EXTENSIONS) return extension_event_router_forwarder_; @@ -373,10 +357,6 @@ static int GetQuicLoadServerInfoTimeout( const VariationParameters& quic_trial_params); - // Returns true if QUIC sever information shouldn't be loaded for new servers. - static bool ShouldDisableLoadingServerInfoForNewServers( - const VariationParameters& quic_trial_params); - // Returns the ratio of time to load QUIC sever information from disk cache to // 'smoothed RTT' based on field trial. Returns 0 if there is an error parsing // the field trial params, or if the default value should be used.
diff --git a/chrome/browser/io_thread_unittest.cc b/chrome/browser/io_thread_unittest.cc index 47bb66bb..43c4669 100644 --- a/chrome/browser/io_thread_unittest.cc +++ b/chrome/browser/io_thread_unittest.cc
@@ -132,7 +132,6 @@ EXPECT_FALSE(params.quic_always_require_handshake_confirmation); EXPECT_FALSE(params.quic_disable_connection_pooling); EXPECT_EQ(0, params.quic_load_server_info_timeout_ms); - EXPECT_FALSE(params.quic_disable_loading_server_info_for_new_servers); EXPECT_EQ(0.0f, params.quic_load_server_info_timeout_srtt_multiplier); EXPECT_FALSE(params.quic_enable_truncated_connection_ids); } @@ -279,15 +278,6 @@ EXPECT_EQ(50, params.quic_load_server_info_timeout_ms); } -TEST_F(IOThreadTest, QuicDisableLoadingServerInfoForNewServers) { - field_trial_group_ = "Enabled"; - field_trial_params_["disable_loading_server_info_for_new_servers"] = "true"; - ConfigureQuicGlobals(); - net::HttpNetworkSession::Params params; - InitializeNetworkSessionParams(¶ms); - EXPECT_TRUE(params.quic_disable_loading_server_info_for_new_servers); -} - TEST_F(IOThreadTest, QuicLoadServerInfoTimeToSmoothedRttFromFieldTrialParams) { field_trial_group_ = "Enabled"; field_trial_params_["load_server_info_time_to_srtt"] = "0.5";
diff --git a/chrome/browser/load_library_perf_test.cc b/chrome/browser/load_library_perf_test.cc index ec48311..7f400b4 100644 --- a/chrome/browser/load_library_perf_test.cc +++ b/chrome/browser/load_library_perf_test.cc
@@ -29,10 +29,10 @@ true); base::NativeLibraryLoadError error; - base::TimeTicks start = base::TimeTicks::HighResNow(); + base::TimeTicks start = base::TimeTicks::Now(); base::NativeLibrary native_library = base::LoadNativeLibrary(library_path, &error); - double delta = (base::TimeTicks::HighResNow() - start).InMillisecondsF(); + double delta = (base::TimeTicks::Now() - start).InMillisecondsF(); ASSERT_TRUE(native_library) << "Error loading library: " << error.ToString(); base::UnloadNativeLibrary(native_library); perf_test::PrintResult("time_to_load_library",
diff --git a/chrome/browser/local_discovery/device_description.cc b/chrome/browser/local_discovery/device_description.cc index d2faed0..71e748db 100644 --- a/chrome/browser/local_discovery/device_description.cc +++ b/chrome/browser/local_discovery/device_description.cc
@@ -15,66 +15,43 @@ namespace { -DeviceDescription::ConnectionState -ConnectionStateFromString(const std::string& str) { - if (LowerCaseEqualsASCII(str, kPrivetConnectionStatusOnline)) { - return DeviceDescription::ONLINE; - } else if (LowerCaseEqualsASCII(str, kPrivetConnectionStatusOffline)) { - return DeviceDescription::OFFLINE; - } else if (LowerCaseEqualsASCII(str, kPrivetConnectionStatusConnecting)) { - return DeviceDescription::CONNECTING; - } else if (LowerCaseEqualsASCII(str, kPrivetConnectionStatusNotConfigured)) { - return DeviceDescription::NOT_CONFIGURED; +std::string GetValueByName(const std::vector<std::string>& metadata, + const std::string& name) { + std::string prefix(name + "="); + for (const std::string& record : metadata) { + if (StartsWithASCII(record, prefix, false)) { + return record.substr(prefix.size()); + } } - - return DeviceDescription::UNKNOWN; + return std::string(); } } // namespace -DeviceDescription::DeviceDescription() - : version(0), - connection_state(UNKNOWN) { +DeviceDescription::DeviceDescription() : version(0) { +} + +DeviceDescription::DeviceDescription( + const ServiceDescription& service_description) { + address = service_description.address; + + const std::vector<std::string>& metadata = service_description.metadata; + if (!base::StringToInt(GetValueByName(metadata, kPrivetTxtKeyVersion), + &version)) { + version = 0; + } + name = GetValueByName(metadata, kPrivetTxtKeyName); + description = GetValueByName(metadata, kPrivetTxtKeyDescription); + if (version >= 3) { + type = GetValueByName(metadata, kPrivetTxtKeyDevicesClass); + id = GetValueByName(metadata, kPrivetTxtKeyGcdID); + } else { + type = GetValueByName(metadata, kPrivetTxtKeyType); + id = GetValueByName(metadata, kPrivetTxtKeyID); + } } DeviceDescription::~DeviceDescription() { } -void DeviceDescription::FillFromServiceDescription( - const ServiceDescription& service_description) { - address = service_description.address; - ip_address = service_description.ip_address; - last_seen = service_description.last_seen; - - for (std::vector<std::string>::const_iterator i = - service_description.metadata.begin(); - i != service_description.metadata.end(); - i++) { - size_t equals_pos = i->find_first_of('='); - if (equals_pos == std::string::npos) - continue; // We do not parse non key-value TXT records - - std::string key = i->substr(0, equals_pos); - std::string value = i->substr(equals_pos + 1); - - if (LowerCaseEqualsASCII(key, kPrivetTxtKeyVersion)) { - if (!base::StringToInt(value, &version)) - continue; // Unknown version. - } else if (LowerCaseEqualsASCII(key, kPrivetTxtKeyName)) { - name = value; - } else if (LowerCaseEqualsASCII(key, kPrivetTxtKeyDescription)) { - description = value; - } else if (LowerCaseEqualsASCII(key, kPrivetTxtKeyURL)) { - url = value; - } else if (LowerCaseEqualsASCII(key, kPrivetTxtKeyType)) { - type = value; - } else if (LowerCaseEqualsASCII(key, kPrivetTxtKeyID)) { - id = value; - } else if (LowerCaseEqualsASCII(key, kPrivetTxtKeyConnectionState)) { - connection_state = ConnectionStateFromString(value); - } - } -} - - } // namespace local_discovery
diff --git a/chrome/browser/local_discovery/device_description.h b/chrome/browser/local_discovery/device_description.h index 2710b7b..1682e0de 100644 --- a/chrome/browser/local_discovery/device_description.h +++ b/chrome/browser/local_discovery/device_description.h
@@ -16,35 +16,23 @@ struct ServiceDescription; struct DeviceDescription { - enum ConnectionState { - ONLINE, - OFFLINE, - CONNECTING, - NOT_CONFIGURED, - UNKNOWN - }; - DeviceDescription(); + explicit DeviceDescription(const ServiceDescription& service_description); ~DeviceDescription(); - void FillFromServiceDescription( - const ServiceDescription& service_description); + bool IsValid() const; // Display attributes std::string name; std::string description; // Functional attributes - std::string url; std::string id; std::string type; int version; - ConnectionState connection_state; // Attributes related to local HTTP net::HostPortPair address; - net::IPAddressNumber ip_address; - base::Time last_seen; }; } // namespace local_discovery
diff --git a/chrome/browser/local_discovery/privet_constants.cc b/chrome/browser/local_discovery/privet_constants.cc index a2a4871..a148901 100644 --- a/chrome/browser/local_discovery/privet_constants.cc +++ b/chrome/browser/local_discovery/privet_constants.cc
@@ -53,6 +53,8 @@ const char kPrivetTxtKeyType[] = "type"; const char kPrivetTxtKeyID[] = "id"; const char kPrivetTxtKeyConnectionState[] = "cs"; +const char kPrivetTxtKeyGcdID[] = "gcd_id"; +const char kPrivetTxtKeyDevicesClass[] = "class"; const char kPrivetConnectionStatusOnline[] = "online"; const char kPrivetConnectionStatusOffline[] = "offline";
diff --git a/chrome/browser/local_discovery/privet_constants.h b/chrome/browser/local_discovery/privet_constants.h index f0b65414..29c730f 100644 --- a/chrome/browser/local_discovery/privet_constants.h +++ b/chrome/browser/local_discovery/privet_constants.h
@@ -56,6 +56,8 @@ extern const char kPrivetTxtKeyType[]; extern const char kPrivetTxtKeyID[]; extern const char kPrivetTxtKeyConnectionState[]; +extern const char kPrivetTxtKeyGcdID[]; +extern const char kPrivetTxtKeyDevicesClass[]; extern const char kPrivetConnectionStatusOnline[]; extern const char kPrivetConnectionStatusOffline[];
diff --git a/chrome/browser/local_discovery/privet_device_lister_impl.cc b/chrome/browser/local_discovery/privet_device_lister_impl.cc index 13da00c..0c3ee1a 100644 --- a/chrome/browser/local_discovery/privet_device_lister_impl.cc +++ b/chrome/browser/local_discovery/privet_device_lister_impl.cc
@@ -47,11 +47,8 @@ if (!delegate_) return; - DeviceDescription device_description; - device_description.FillFromServiceDescription(service_description); - - delegate_->DeviceChanged( - added, service_description.service_name, device_description); + delegate_->DeviceChanged(added, service_description.service_name, + DeviceDescription(service_description)); } void PrivetDeviceListerImpl::OnDeviceRemoved(const std::string& service_name) {
diff --git a/chrome/browser/local_discovery/privet_device_lister_unittest.cc b/chrome/browser/local_discovery/privet_device_lister_unittest.cc index 0b91e38..3f7dfa9 100644 --- a/chrome/browser/local_discovery/privet_device_lister_unittest.cc +++ b/chrome/browser/local_discovery/privet_device_lister_unittest.cc
@@ -230,12 +230,9 @@ outgoing_description.address.host()); EXPECT_EQ(service_description_.address.port(), outgoing_description.address.port()); - EXPECT_EQ(service_description_.ip_address, outgoing_description.ip_address); - EXPECT_EQ(service_description_.last_seen, outgoing_description.last_seen); EXPECT_EQ("My Printer", outgoing_description.name); EXPECT_EQ("This is my Printer", outgoing_description.description); EXPECT_EQ("", outgoing_description.id); - EXPECT_EQ(DeviceDescription::ONLINE, outgoing_description.connection_state); EXPECT_CALL(delegate_, DeviceRemoved("myprinter._privet._tcp.local"));
diff --git a/chrome/browser/local_discovery/privet_device_resolver.cc b/chrome/browser/local_discovery/privet_device_resolver.cc index 6bbb13b6..915d42c 100644 --- a/chrome/browser/local_discovery/privet_device_resolver.cc +++ b/chrome/browser/local_discovery/privet_device_resolver.cc
@@ -29,14 +29,12 @@ void PrivetDeviceResolver::OnServiceResolved( ServiceResolver::RequestStatus request_status, const ServiceDescription& service_description) { - DeviceDescription device_description; if (request_status != ServiceResolver::STATUS_SUCCESS) { - callback_.Run(false, device_description); + callback_.Run(false, DeviceDescription()); return; } - device_description.FillFromServiceDescription(service_description); - callback_.Run(true, device_description); + callback_.Run(true, DeviceDescription(service_description)); } } // namespace local_discovery
diff --git a/chrome/browser/local_discovery/privet_http_impl.cc b/chrome/browser/local_discovery/privet_http_impl.cc index 68fa5a0..dd340df 100644 --- a/chrome/browser/local_discovery/privet_http_impl.cc +++ b/chrome/browser/local_discovery/privet_http_impl.cc
@@ -11,22 +11,21 @@ #include "base/message_loop/message_loop.h" #include "base/rand_util.h" #include "base/strings/string_number_conversions.h" -#include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/local_discovery/privet_constants.h" -#include "components/cloud_devices/common/printer_description.h" #include "net/base/url_util.h" -#include "printing/pwg_raster_settings.h" -#include "printing/units.h" -#include "ui/gfx/text_elider.h" #include "url/gurl.h" #if defined(ENABLE_PRINT_PREVIEW) #include "chrome/browser/local_discovery/pwg_raster_converter.h" +#include "components/cloud_devices/common/printer_description.h" +#include "printing/pdf_render_settings.h" +#include "printing/pwg_raster_settings.h" +#include "printing/units.h" +#include "ui/gfx/geometry/rect.h" +#include "ui/gfx/text_elider.h" #endif // ENABLE_PRINT_PREVIEW -using namespace cloud_devices::printer; - namespace cloud_print { extern const char kContentTypeJSON[]; } @@ -390,81 +389,6 @@ privet_client_->RefreshPrivetToken(callback); } -PrivetDataReadOperationImpl::PrivetDataReadOperationImpl( - PrivetHTTPClient* privet_client, - const std::string& path, - const std::string& query_params, - const PrivetDataReadOperation::ResultCallback& callback) - : privet_client_(privet_client), - path_(path), - query_params_(query_params), - callback_(callback), - has_range_(false), - save_to_file_(false) { -} - -PrivetDataReadOperationImpl::~PrivetDataReadOperationImpl() { -} - - -void PrivetDataReadOperationImpl::Start() { - url_fetcher_ = privet_client_->CreateURLFetcher( - CreatePrivetParamURL(path_, query_params_), net::URLFetcher::GET, this); - url_fetcher_->DoNotRetryOnTransientError(); - - if (has_range_) { - url_fetcher_->SetByteRange(range_start_, range_end_); - } - - if (save_to_file_) { - url_fetcher_->SaveResponseToFile(); - } - - url_fetcher_->Start(); -} - -void PrivetDataReadOperationImpl::SetDataRange(int range_start, int range_end) { - has_range_ = true; - range_start_ = range_start; - range_end_ = range_end; -} - -void PrivetDataReadOperationImpl::SaveDataToFile() { - save_to_file_ = false; -} - -PrivetHTTPClient* PrivetDataReadOperationImpl::GetHTTPClient() { - return privet_client_; -} - -void PrivetDataReadOperationImpl::OnError( - PrivetURLFetcher* fetcher, - PrivetURLFetcher::ErrorType error) { - callback_.Run(RESPONSE_TYPE_ERROR, std::string(), base::FilePath()); -} - -void PrivetDataReadOperationImpl::OnParsedJson( - PrivetURLFetcher* fetcher, - const base::DictionaryValue& value, - bool has_error) { - NOTREACHED(); -} - -void PrivetDataReadOperationImpl::OnNeedPrivetToken( - PrivetURLFetcher* fetcher, - const PrivetURLFetcher::TokenCallback& callback) { - privet_client_->RefreshPrivetToken(callback); -} - -bool PrivetDataReadOperationImpl::OnRawData(PrivetURLFetcher* fetcher, - bool is_file, - const std::string& data_str, - const base::FilePath& file_path) { - ResponseType type = (is_file) ? RESPONSE_TYPE_FILE : RESPONSE_TYPE_STRING; - callback_.Run(type, data_str, file_path); - return true; -} - #if defined(ENABLE_PRINT_PREVIEW) PrivetLocalPrintOperationImpl::PrivetLocalPrintOperationImpl( PrivetHTTPClient* privet_client, @@ -528,6 +452,7 @@ void PrivetLocalPrintOperationImpl::StartInitialRequest() { use_pdf_ = false; + using namespace cloud_devices::printer; ContentTypesCapability content_types; if (content_types.LoadFrom(capabilities_)) { use_pdf_ = content_types.Contains(kPrivetContentTypePDF) || @@ -550,7 +475,7 @@ &PrivetLocalPrintOperationImpl::OnCreatejobResponse, base::Unretained(this)); - url_fetcher_= privet_client_->CreateURLFetcher( + url_fetcher_ = privet_client_->CreateURLFetcher( CreatePrivetURL(kPrivetCreatejobPath), net::URLFetcher::POST, this); url_fetcher_->SetUploadData(cloud_print::kContentTypeJSON, ticket_.ToString()); @@ -598,8 +523,8 @@ kPrivetURLValueOffline); } - url_fetcher_= privet_client_->CreateURLFetcher( - url, net::URLFetcher::POST, this); + url_fetcher_ = + privet_client_->CreateURLFetcher(url, net::URLFetcher::POST, this); if (!use_pdf_) { url_fetcher_->SetUploadFilePath(kPrivetContentTypePWGRaster, @@ -623,6 +548,7 @@ void PrivetLocalPrintOperationImpl::FillPwgRasterSettings( printing::PwgRasterSettings* transform_settings) { + using namespace cloud_devices::printer; PwgRasterConfigCapability raster_capability; // If the raster capability fails to load, raster_capability will contain // the default value. @@ -803,7 +729,7 @@ void PrivetLocalPrintOperationImpl::SetUsername(const std::string& user) { DCHECK(!started_); - user_= user; + user_ = user; } void PrivetLocalPrintOperationImpl::SetJobname(const std::string& jobname) {
diff --git a/chrome/browser/local_discovery/privet_http_impl.h b/chrome/browser/local_discovery/privet_http_impl.h index e5d6c3b..49d11be 100644 --- a/chrome/browser/local_discovery/privet_http_impl.h +++ b/chrome/browser/local_discovery/privet_http_impl.h
@@ -9,12 +9,12 @@ #include <vector> #include "base/callback.h" -#include "base/files/file_util.h" +#include "base/files/file_path.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "chrome/browser/local_discovery/privet_http.h" #include "components/cloud_devices/common/cloud_device_description.h" -#include "printing/pdf_render_settings.h" +#include "ui/gfx/geometry/size.h" namespace printing { struct PwgRasterSettings; @@ -150,51 +150,6 @@ scoped_ptr<PrivetURLFetcher> url_fetcher_; }; -class PrivetDataReadOperationImpl : public PrivetDataReadOperation, - public PrivetURLFetcher::Delegate { - public: - PrivetDataReadOperationImpl( - PrivetHTTPClient* privet_client, - const std::string& path, - const std::string& query_params, - const PrivetDataReadOperation::ResultCallback& callback); - ~PrivetDataReadOperationImpl() override; - - void Start() override; - - void SetDataRange(int range_start, int range_end) override; - - void SaveDataToFile() override; - - PrivetHTTPClient* GetHTTPClient() override; - - void OnError(PrivetURLFetcher* fetcher, - PrivetURLFetcher::ErrorType error) override; - void OnParsedJson(PrivetURLFetcher* fetcher, - const base::DictionaryValue& value, - bool has_error) override; - void OnNeedPrivetToken( - PrivetURLFetcher* fetcher, - const PrivetURLFetcher::TokenCallback& callback) override; - bool OnRawData(PrivetURLFetcher* fetcher, - bool is_file, - const std::string& data_str, - const base::FilePath& file_path) override; - - private: - PrivetHTTPClient* privet_client_; - std::string path_; - std::string query_params_; - int range_start_; - int range_end_; - PrivetDataReadOperation::ResultCallback callback_; - - bool has_range_; - bool save_to_file_; - - scoped_ptr<PrivetURLFetcher> url_fetcher_; -}; - #if defined(ENABLE_PRINT_PREVIEW) class PrivetLocalPrintOperationImpl : public PrivetLocalPrintOperation,
diff --git a/chrome/browser/local_discovery/privet_notifications.cc b/chrome/browser/local_discovery/privet_notifications.cc index 7824b4e9..a6f19c4 100644 --- a/chrome/browser/local_discovery/privet_notifications.cc +++ b/chrome/browser/local_discovery/privet_notifications.cc
@@ -269,7 +269,6 @@ body, ui::ResourceBundle::GetSharedInstance().GetImageNamed( IDR_LOCAL_DISCOVERY_CLOUDPRINT_ICON), - blink::WebTextDirectionDefault, message_center::NotifierId(GURL(kPrivetNotificationOriginUrl)), product_name, base::UTF8ToUTF16(kPrivetNotificationID),
diff --git a/chrome/browser/local_discovery/privet_url_fetcher.cc b/chrome/browser/local_discovery/privet_url_fetcher.cc index 627278ea..a5cc2855 100644 --- a/chrome/browser/local_discovery/privet_url_fetcher.cc +++ b/chrome/browser/local_discovery/privet_url_fetcher.cc
@@ -34,7 +34,7 @@ }; const char kXPrivetTokenHeaderPrefix[] = "X-Privet-Token: "; -const char kXPrivetAuthTokenHeaderPrefix[] = "X-Privet-Auth: "; +const char kPrivetV3AuthTokenHeaderPrefix[] = "Authorization: "; const char kRangeHeaderFormat[] = "Range: bytes=%d-%d"; const char kXPrivetEmptyToken[] = "\"\""; const char kPrivetAuthTokenUnknown[] = "Unknown"; @@ -151,10 +151,9 @@ url_fetcher_->SetRequestContext(request_context_.get()); if (v3_mode_) { - std::string auth_token = delegate_->GetAuthToken(); - url_fetcher_->AddExtraRequestHeader( - std::string(kXPrivetAuthTokenHeaderPrefix) + auth_token); + std::string(kPrivetV3AuthTokenHeaderPrefix) + + delegate_->GetAuthToken()); } else { std::string token = GetPrivetAccessToken();
diff --git a/chrome/browser/local_discovery/privet_url_fetcher_unittest.cc b/chrome/browser/local_discovery/privet_url_fetcher_unittest.cc index 5d07b8a..2b1daca 100644 --- a/chrome/browser/local_discovery/privet_url_fetcher_unittest.cc +++ b/chrome/browser/local_discovery/privet_url_fetcher_unittest.cc
@@ -311,7 +311,8 @@ std::string header_token; ASSERT_FALSE(headers.GetHeader("X-Privet-Token", &header_token)); - ASSERT_TRUE(headers.GetHeader("X-Privet-Auth", &header_token)); + ASSERT_FALSE(headers.GetHeader("X-Privet-Auth", &header_token)); + ASSERT_TRUE(headers.GetHeader("Authorization", &header_token)); ASSERT_EQ("MyAuthToken", header_token); }
diff --git a/chrome/browser/local_discovery/privetv3_crypto_provider.cc b/chrome/browser/local_discovery/privetv3_crypto_provider.cc deleted file mode 100644 index 819df06b..0000000 --- a/chrome/browser/local_discovery/privetv3_crypto_provider.cc +++ /dev/null
@@ -1,113 +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 "chrome/browser/local_discovery/privetv3_crypto_provider.h" - -#include "base/logging.h" - -namespace local_discovery { - -namespace { - -// A stub session type used for development/debugging. -const char kAuthMethodEmpty[] = "empty"; - -const char kHandshakeStateComplete[] = "complete"; -const char kStubVerificationCode[] = "SAMPLE"; -} - -class PrivetV3CryptoProviderEmpty : public PrivetV3CryptoProvider { - public: - PrivetV3CryptoProviderEmpty(); - ~PrivetV3CryptoProviderEmpty() override; - - // PrivetV3CryptoProvider implementation. - HandshakeState GetState() override; - std::string GetAuthMethod() override; - HandshakeState GetNextStep(int* step, std::string* package) override; - HandshakeState SetStepResponse(int step, - const std::string& state, - const std::string& package) override; - std::string GetVerificationCode() override; - HandshakeState AcceptVerificationCode() override; - bool EncryptData(const std::string& input, std::string* output) override; - - private: - HandshakeState state_; -}; - -scoped_ptr<PrivetV3CryptoProvider> Create( - const std::vector<std::string>& available_auth_methods) { - for (size_t i = 0; i < available_auth_methods.size(); i++) { - if (available_auth_methods[i] == kAuthMethodEmpty) { - return scoped_ptr<PrivetV3CryptoProvider>( - new PrivetV3CryptoProviderEmpty()); - } - } - - return scoped_ptr<PrivetV3CryptoProvider>(); -} - -PrivetV3CryptoProviderEmpty::PrivetV3CryptoProviderEmpty() - : state_(IN_PROGRESS) { -} - -PrivetV3CryptoProviderEmpty::~PrivetV3CryptoProviderEmpty() { -} - -PrivetV3CryptoProvider::HandshakeState PrivetV3CryptoProviderEmpty::GetState() { - return state_; -} - -std::string PrivetV3CryptoProviderEmpty::GetAuthMethod() { - return kAuthMethodEmpty; -} - -PrivetV3CryptoProvider::HandshakeState PrivetV3CryptoProviderEmpty::GetNextStep( - int* step, - std::string* package) { - DCHECK(state_ == IN_PROGRESS); - *step = 0; - package->clear(); - state_ = AWAITING_RESPONSE; - - return state_; -} - -PrivetV3CryptoProvider::HandshakeState -PrivetV3CryptoProviderEmpty::SetStepResponse(int step, - const std::string& state, - const std::string& package) { - DCHECK(state_ == AWAITING_RESPONSE); - - bool success = - (step == 0 && package.empty() && state == kHandshakeStateComplete); - - if (success) { - state_ = AWAITING_USER_VERIFICATION; - } else { - state_ = HANDSHAKE_ERROR; - } - - return state_; -} - -std::string PrivetV3CryptoProviderEmpty::GetVerificationCode() { - DCHECK(state_ == AWAITING_USER_VERIFICATION); - return kStubVerificationCode; -} - -PrivetV3CryptoProvider::HandshakeState -PrivetV3CryptoProviderEmpty::AcceptVerificationCode() { - DCHECK(state_ == AWAITING_USER_VERIFICATION); - return (state_ = HANDSHAKE_COMPLETE); -} - -bool PrivetV3CryptoProviderEmpty::EncryptData(const std::string& input, - std::string* output) { - *output = input; - return true; -} - -} // namespace local_discovery
diff --git a/chrome/browser/local_discovery/privetv3_crypto_provider.h b/chrome/browser/local_discovery/privetv3_crypto_provider.h deleted file mode 100644 index 8f4f0758..0000000 --- a/chrome/browser/local_discovery/privetv3_crypto_provider.h +++ /dev/null
@@ -1,70 +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 CHROME_BROWSER_LOCAL_DISCOVERY_PRIVETV3_CRYPTO_PROVIDER_H_ -#define CHROME_BROWSER_LOCAL_DISCOVERY_PRIVETV3_CRYPTO_PROVIDER_H_ - -#include <string> -#include <vector> - -#include "base/memory/scoped_ptr.h" - -namespace local_discovery { - -class PrivetV3CryptoProvider { - public: - enum HandshakeState { - // Handshake still in progress. Call |GetNextStep| to send next handshake - // step. - IN_PROGRESS, - // Handshake in progress, waiting for response. Call |SetStepResponse| to - // set the step response. - AWAITING_RESPONSE, - // Handshake in progress, need to wait for user verification to - // continue. Call |GetVerificationCode| to get the verification code and - // |AcceptVerificationCode| to signify the code is accepted. - AWAITING_USER_VERIFICATION, - // Handshake complete. Call |EncryptData| to encrypt the data. - HANDSHAKE_COMPLETE, - // Handshake error. - HANDSHAKE_ERROR - }; - - virtual ~PrivetV3CryptoProvider() {} - - static scoped_ptr<PrivetV3CryptoProvider> Create( - const std::vector<std::string>& available_auth_methods); - - // Return the current state of the crypto provider. - virtual HandshakeState GetState() = 0; - - // Return the authentication method used. - virtual std::string GetAuthMethod() = 0; - - // Get the next handshake command. |step| is the step number to send, - // |package| is a base64-encoded package to send with the step. Return - // |true| if a package is generated or |false| in case of an error. - virtual HandshakeState GetNextStep(int* step, std::string* package) = 0; - - // Input the response to the handshake command. |step| is the received step - // number, |state| is the received state string, |package| is the received - // base64-encoded package. Return the current handshake state. - virtual HandshakeState SetStepResponse(int step, - const std::string& state, - const std::string& package) = 0; - - // Get the verification code to be displayed on the screen. - virtual std::string GetVerificationCode() = 0; - - // Signal that the verification code is accepted. Returns the current - // handshake state. - virtual HandshakeState AcceptVerificationCode() = 0; - - // Encrypt a string using the session key. - virtual bool EncryptData(const std::string& input, std::string* output) = 0; -}; - -} // namespace local_discovery - -#endif // CHROME_BROWSER_LOCAL_DISCOVERY_PRIVETV3_CRYPTO_PROVIDER_H_
diff --git a/chrome/browser/local_discovery/privetv3_session.cc b/chrome/browser/local_discovery/privetv3_session.cc index 18c3ff6..bd5f4ca6 100644 --- a/chrome/browser/local_discovery/privetv3_session.cc +++ b/chrome/browser/local_discovery/privetv3_session.cc
@@ -7,8 +7,11 @@ #include "base/json/json_writer.h" #include "base/logging.h" #include "base/message_loop/message_loop.h" +#include "chrome/browser/local_discovery/privet_constants.h" #include "chrome/browser/local_discovery/privet_http.h" +#include "chrome/browser/local_discovery/privet_url_fetcher.h" #include "chrome/common/cloud_print/cloud_print_constants.h" +#include "url/gurl.h" namespace local_discovery { @@ -18,6 +21,8 @@ const char kStubPrivetCode[] = "1234"; +const char kPrivetV3AuthAnonymous[] = "Privet anonymous"; + GURL CreatePrivetURL(const std::string& path) { GURL url(kUrlPlaceHolder); GURL::Replacements replacements; @@ -30,10 +35,12 @@ class PrivetV3Session::FetcherDelegate : public PrivetURLFetcher::Delegate { public: FetcherDelegate(const base::WeakPtr<PrivetV3Session>& session, + const std::string& auth_token, const PrivetV3Session::MessageCallback& callback); ~FetcherDelegate() override; // PrivetURLFetcher::Delegate methods. + std::string GetAuthToken() override; void OnNeedPrivetToken( PrivetURLFetcher* fetcher, const PrivetURLFetcher::TokenCallback& callback) override; @@ -49,22 +56,29 @@ scoped_ptr<PrivetURLFetcher> url_fetcher_; base::WeakPtr<PrivetV3Session> session_; + std::string auth_token_; MessageCallback callback_; }; PrivetV3Session::FetcherDelegate::FetcherDelegate( const base::WeakPtr<PrivetV3Session>& session, + const std::string& auth_token, const PrivetV3Session::MessageCallback& callback) - : session_(session), callback_(callback) { + : session_(session), auth_token_(auth_token), callback_(callback) { } PrivetV3Session::FetcherDelegate::~FetcherDelegate() { } +std::string PrivetV3Session::FetcherDelegate::GetAuthToken() { + return auth_token_; +} + void PrivetV3Session::FetcherDelegate::OnNeedPrivetToken( PrivetURLFetcher* fetcher, const PrivetURLFetcher::TokenCallback& callback) { NOTREACHED(); + OnError(fetcher, PrivetURLFetcher::URL_FETCH_ERROR); } void PrivetV3Session::FetcherDelegate::OnError( @@ -93,12 +107,6 @@ base::Unretained(this))); } -PrivetV3Session::Request::Request() { -} - -PrivetV3Session::Request::~Request() { -} - PrivetV3Session::PrivetV3Session(scoped_ptr<PrivetHTTPClient> client) : client_(client.Pass()), code_confirmed_(false), weak_ptr_factory_(this) { } @@ -107,6 +115,8 @@ } void PrivetV3Session::Init(const InitCallback& callback) { + privet_auth_token_ = kPrivetV3AuthAnonymous; + // TODO: call /info. base::MessageLoop::current()->PostDelayedTask( FROM_HERE, @@ -144,8 +154,8 @@ if (!code_confirmed_) return callback.Run(Result::STATUS_SESSIONERROR, base::DictionaryValue()); - FetcherDelegate* fetcher_delegate( - new FetcherDelegate(weak_ptr_factory_.GetWeakPtr(), callback)); + FetcherDelegate* fetcher_delegate(new FetcherDelegate( + weak_ptr_factory_.GetWeakPtr(), privet_auth_token_, callback)); fetchers_.push_back(fetcher_delegate); scoped_ptr<PrivetURLFetcher> url_fetcher(client_->CreateURLFetcher(
diff --git a/chrome/browser/local_discovery/privetv3_session.h b/chrome/browser/local_discovery/privetv3_session.h index d03f9b6..648eef7a 100644 --- a/chrome/browser/local_discovery/privetv3_session.h +++ b/chrome/browser/local_discovery/privetv3_session.h
@@ -10,7 +10,7 @@ #include "base/callback.h" #include "base/memory/scoped_ptr.h" #include "base/memory/scoped_vector.h" -#include "chrome/browser/local_discovery/privet_url_fetcher.h" +#include "base/memory/weak_ptr.h" #include "chrome/common/extensions/api/gcd_private.h" namespace base { @@ -54,27 +54,14 @@ const MessageCallback& callback); private: - // Represents request in progress using secure session. - class Request { - public: - Request(); - virtual ~Request(); - - virtual void OnError() = 0; - virtual void OnParsedJson(const base::DictionaryValue& value, - bool has_error) = 0; - - private: - friend class PrivetV3Session; - scoped_ptr<FetcherDelegate> fetcher_delegate_; - }; - void RunCallback(const base::Closure& callback); void DeleteFetcher(const FetcherDelegate* fetcher); scoped_ptr<PrivetHTTPClient> client_; bool code_confirmed_; ScopedVector<FetcherDelegate> fetchers_; + std::string privet_auth_token_; + base::WeakPtrFactory<PrivetV3Session> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(PrivetV3Session); };
diff --git a/chrome/browser/local_discovery/privetv3_setup_flow.cc b/chrome/browser/local_discovery/privetv3_setup_flow.cc deleted file mode 100644 index 59feaa09..0000000 --- a/chrome/browser/local_discovery/privetv3_setup_flow.cc +++ /dev/null
@@ -1,122 +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 "chrome/browser/local_discovery/privetv3_setup_flow.h" - -#include "base/logging.h" -#include "chrome/browser/local_discovery/gcd_registration_ticket_request.h" - -namespace local_discovery { - -namespace { - -const char kTicketJsonKeyName[] = "registration.ticketID"; -const char kUserJsonKeyName[] = "registration.user"; - -} // namespace - -PrivetV3SetupFlow::Delegate::~Delegate() { -} - -PrivetV3SetupFlow::PrivetV3SetupFlow(Delegate* delegate) - : delegate_(delegate), weak_ptr_factory_(this) { -} - -PrivetV3SetupFlow::~PrivetV3SetupFlow() { -} - -void PrivetV3SetupFlow::Register(const std::string& service_name) { - service_name_ = service_name; - ticket_request_ = delegate_->CreateApiFlow(); - if (!ticket_request_) { - OnSetupError(); - return; - } - scoped_ptr<GCDApiFlow::Request> ticket_request( - new GCDRegistrationTicketRequest( - base::Bind(&PrivetV3SetupFlow::OnTicketCreated, - weak_ptr_factory_.GetWeakPtr()))); - ticket_request_->Start(ticket_request.Pass()); -} - -#if defined(ENABLE_WIFI_BOOTSTRAPPING) -void PrivetV3SetupFlow::SetupWifiAndRegister(const std::string& device_ssid) { - NOTIMPLEMENTED(); -} -#endif // ENABLE_WIFI_BOOTSTRAPPING - -void PrivetV3SetupFlow::OnSetupError() { - delegate_->OnSetupError(); -} - -void PrivetV3SetupFlow::OnTicketCreated(const std::string& ticket_id, - const std::string& device_id) { - if (ticket_id.empty() || device_id.empty()) { - OnSetupError(); - return; - } - // TODO(vitalybuka): Implement success check by polling status of device_id_. - device_id_ = device_id; - ticket_id_ = ticket_id; - delegate_->CreatePrivetV3Client( - service_name_, - base::Bind(&PrivetV3SetupFlow::OnPrivetClientCreated, - weak_ptr_factory_.GetWeakPtr())); -} - -void PrivetV3SetupFlow::OnPrivetClientCreated( - scoped_ptr<PrivetHTTPClient> privet_http_client) { - if (!privet_http_client) { - OnSetupError(); - return; - } - session_.reset(new PrivetV3Session(privet_http_client.Pass())); - session_->Init(base::Bind(&PrivetV3SetupFlow::OnSessionInitialized, - weak_ptr_factory_.GetWeakPtr())); -} - -void PrivetV3SetupFlow::OnCodeConfirmed(bool success) { - if (!success) - return OnSetupError(); - session_->ConfirmCode("1234", base::Bind(&PrivetV3SetupFlow::OnPairingDone, - weak_ptr_factory_.GetWeakPtr())); -} - -void PrivetV3SetupFlow::OnSessionInitialized( - PrivetV3Session::Result result, - const std::vector<PrivetV3Session::PairingType>& types) { - if (result != PrivetV3Session::Result::STATUS_SUCCESS) - return OnSetupError(); - session_->StartPairing(PrivetV3Session::PairingType::PAIRING_TYPE_PINCODE, - base::Bind(&PrivetV3SetupFlow::OnPairingStarted, - weak_ptr_factory_.GetWeakPtr())); -} - -void PrivetV3SetupFlow::OnPairingStarted(PrivetV3Session::Result result) { - if (result != PrivetV3Session::Result::STATUS_SUCCESS) - return OnSetupError(); - delegate_->ConfirmSecurityCode(base::Bind(&PrivetV3SetupFlow::OnCodeConfirmed, - weak_ptr_factory_.GetWeakPtr())); -} - -void PrivetV3SetupFlow::OnPairingDone(PrivetV3Session::Result result) { - if (result != PrivetV3Session::Result::STATUS_SUCCESS) - return OnSetupError(); - base::DictionaryValue message; - message.SetString(kTicketJsonKeyName, ticket_id_); - message.SetString(kUserJsonKeyName, "me"); - session_->SendMessage("/privet/v3/setup/start", message, - base::Bind(&PrivetV3SetupFlow::OnSetupMessageSent, - weak_ptr_factory_.GetWeakPtr())); -} - -void PrivetV3SetupFlow::OnSetupMessageSent( - PrivetV3Session::Result result, - const base::DictionaryValue& response) { - if (result != PrivetV3Session::Result::STATUS_SUCCESS) - return OnSetupError(); - delegate_->OnSetupDone(); -} - -} // namespace local_discovery
diff --git a/chrome/browser/local_discovery/privetv3_setup_flow.h b/chrome/browser/local_discovery/privetv3_setup_flow.h deleted file mode 100644 index 401693d..0000000 --- a/chrome/browser/local_discovery/privetv3_setup_flow.h +++ /dev/null
@@ -1,104 +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 CHROME_BROWSER_LOCAL_DISCOVERY_PRIVETV3_SETUP_FLOW_H_ -#define CHROME_BROWSER_LOCAL_DISCOVERY_PRIVETV3_SETUP_FLOW_H_ - -#include <string> - -#include "base/callback.h" -#include "base/memory/scoped_ptr.h" -#include "chrome/browser/local_discovery/gcd_api_flow.h" -#include "chrome/browser/local_discovery/privet_http.h" -#include "chrome/browser/local_discovery/privetv3_session.h" - -namespace local_discovery { - -// Provides complete flow for Privet v3 device setup. -class PrivetV3SetupFlow { - public: - // Delegate to be implemented by client code. - class Delegate { - public: - typedef base::Callback<void(bool success)> ResultCallback; - // If |ssid| is empty, call failed to get credentials. - // If |key| is empty, network is open. - typedef base::Callback<void(const std::string& ssid, - const std::string& key)> CredentialsCallback; - - typedef base::Callback<void(scoped_ptr<PrivetHTTPClient>)> - PrivetClientCallback; - - virtual ~Delegate(); - - // Creates |GCDApiFlowImpl| for making requests to GCD server. - virtual scoped_ptr<GCDApiFlow> CreateApiFlow() = 0; - - // Requests WiFi credentials. - virtual void GetWiFiCredentials(const CredentialsCallback& callback) = 0; - - // Switches to setup WiFi network. - // If switch was successfully |RestoreWifi| should be called later. - virtual void SwitchToSetupWiFi(const ResultCallback& callback) = 0; - - // Starts device resolution that should callback with ready - // |PrivetV3HTTPClient|. - virtual void CreatePrivetV3Client(const std::string& service_name, - const PrivetClientCallback& callback) = 0; - - // Requests client to prompt user to check pairing code. - virtual void ConfirmSecurityCode(const ResultCallback& callback) = 0; - - // Restores WiFi network. - virtual void RestoreWifi(const ResultCallback& callback) = 0; - - // Notifies client that device is set up. - virtual void OnSetupDone() = 0; - - // Notifies client setup failed. - virtual void OnSetupError() = 0; - }; - - explicit PrivetV3SetupFlow(Delegate* delegate); - virtual ~PrivetV3SetupFlow(); - - // Starts registration. - void Register(const std::string& service_name); - -#if defined(ENABLE_WIFI_BOOTSTRAPPING) - void SetupWifiAndRegister(const std::string& device_ssid); -#endif // ENABLE_WIFI_BOOTSTRAPPING - - void OnSetupError(); - - const std::string& service_name() const { return service_name_; } - - private: - void OnTicketCreated(const std::string& ticket_id, - const std::string& device_id); - void OnPrivetClientCreated(scoped_ptr<PrivetHTTPClient> privet_http_client); - void OnCodeConfirmed(bool success); - - void OnSessionInitialized( - PrivetV3Session::Result result, - const std::vector<PrivetV3Session::PairingType>& types); - void OnPairingStarted(PrivetV3Session::Result result); - void OnPairingDone(PrivetV3Session::Result result); - void OnSetupMessageSent(PrivetV3Session::Result result, - const base::DictionaryValue& response); - - Delegate* delegate_; - std::string service_name_; - std::string device_id_; - std::string ticket_id_; - scoped_ptr<GCDApiFlow> ticket_request_; - scoped_ptr<PrivetV3Session> session_; - base::WeakPtrFactory<PrivetV3SetupFlow> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(PrivetV3SetupFlow); -}; - -} // namespace local_discovery - -#endif // CHROME_BROWSER_LOCAL_DISCOVERY_PRIVETV3_SETUP_FLOW_H_
diff --git a/chrome/browser/local_discovery/privetv3_setup_flow_unittest.cc b/chrome/browser/local_discovery/privetv3_setup_flow_unittest.cc deleted file mode 100644 index 9b6ae67..0000000 --- a/chrome/browser/local_discovery/privetv3_setup_flow_unittest.cc +++ /dev/null
@@ -1,193 +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 "chrome/browser/local_discovery/privetv3_setup_flow.h" - -#include "base/json/json_reader.h" -#include "base/run_loop.h" -#include "chrome/browser/local_discovery/gcd_api_flow.h" -#include "net/http/http_response_headers.h" -#include "net/url_request/test_url_fetcher_factory.h" -#include "net/url_request/url_request_test_util.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace local_discovery { - -namespace { - -using testing::HasSubstr; -using testing::Invoke; -using testing::Return; -using testing::SaveArg; -using testing::StrictMock; -using testing::WithArgs; -using testing::_; - -const char kServiceName[] = "test_service"; - -const char kRegistrationTicketResponse[] = - "{" - "\"kind\": \"clouddevices#registrationTicket\"," - "\"id\": \"test_ticket\"," - "\"deviceId\": \"test_id\"" - "}"; - -class MockPrivetHTTPClient : public PrivetHTTPClient { - public: - MockPrivetHTTPClient() { - request_context_ = - new net::TestURLRequestContextGetter(base::MessageLoopProxy::current()); - } - - MOCK_METHOD0(GetName, const std::string&()); - MOCK_METHOD1( - CreateInfoOperationPtr, - PrivetJSONOperation*(const PrivetJSONOperation::ResultCallback&)); - - virtual void RefreshPrivetToken( - const PrivetURLFetcher::TokenCallback& callback) override { - callback.Run("x-privet-token"); - } - - virtual scoped_ptr<PrivetJSONOperation> CreateInfoOperation( - const PrivetJSONOperation::ResultCallback& callback) override { - return make_scoped_ptr(CreateInfoOperationPtr(callback)); - } - - virtual scoped_ptr<PrivetURLFetcher> CreateURLFetcher( - const GURL& url, - net::URLFetcher::RequestType request_type, - PrivetURLFetcher::Delegate* delegate) override { - return make_scoped_ptr(new PrivetURLFetcher( - url, request_type, request_context_.get(), delegate)); - } - - scoped_refptr<net::TestURLRequestContextGetter> request_context_; -}; - -class MockDelegate : public PrivetV3SetupFlow::Delegate { - public: - MockDelegate() : privet_client_ptr_(NULL) {} - - class MockGCDApiFlow : public GCDApiFlow { - public: - explicit MockGCDApiFlow(MockDelegate* delegate) : delegate_(delegate) {} - - void Start(scoped_ptr<Request> request) override { - ASSERT_FALSE(delegate_->gcd_request_); - delegate_->gcd_request_ = request.Pass(); - delegate_->ReplyWithToken(); - } - - private: - MockDelegate* delegate_; - }; - - MOCK_METHOD1(GetWiFiCredentials, void(const CredentialsCallback&)); - MOCK_METHOD1(SwitchToSetupWiFi, void(const ResultCallback&)); - virtual void CreatePrivetV3Client( - const std::string& service_name, - const PrivetClientCallback& callback) override { - scoped_ptr<MockPrivetHTTPClient> privet_client(new MockPrivetHTTPClient()); - privet_client_ptr_ = privet_client.get(); - callback.Run(privet_client.Pass()); - } - MOCK_METHOD1(ConfirmSecurityCode, void(const ResultCallback&)); - MOCK_METHOD1(RestoreWifi, void(const ResultCallback&)); - MOCK_METHOD0(OnSetupDone, void()); - MOCK_METHOD0(OnSetupError, void()); - - virtual scoped_ptr<GCDApiFlow> CreateApiFlow() override { - return make_scoped_ptr(new MockGCDApiFlow(this)); - } - - void ReplyWithToken() { - scoped_ptr<base::Value> value(base::JSONReader::Read(gcd_server_response_)); - const base::DictionaryValue* dictionary = NULL; - value->GetAsDictionary(&dictionary); - gcd_request_->OnGCDAPIFlowComplete(*dictionary); - } - - std::string gcd_server_response_; - scoped_ptr<GCDApiFlow::Request> gcd_request_; - MockPrivetHTTPClient* privet_client_ptr_; - base::Closure quit_closure_; -}; - -class PrivetV3SetupFlowTest : public testing::Test { - public: - PrivetV3SetupFlowTest() : setup_(&delegate_) {} - - virtual ~PrivetV3SetupFlowTest() {} - - void ConfirmCode(const MockDelegate::ResultCallback& confirm_callback) { - base::MessageLoop::current()->PostTask(FROM_HERE, quit_closure_); - confirm_callback.Run(true); - } - - protected: - virtual void SetUp() override { - quit_closure_ = run_loop_.QuitClosure(); - EXPECT_CALL(delegate_, GetWiFiCredentials(_)).Times(0); - EXPECT_CALL(delegate_, SwitchToSetupWiFi(_)).Times(0); - EXPECT_CALL(delegate_, ConfirmSecurityCode(_)).Times(0); - EXPECT_CALL(delegate_, RestoreWifi(_)).Times(0); - EXPECT_CALL(delegate_, OnSetupDone()).Times(0); - EXPECT_CALL(delegate_, OnSetupError()).Times(0); - } - - void SimulateFetch(int response_code, const std::string& response) { - net::TestURLFetcher* fetcher = url_fetcher_factory_.GetFetcherByID(0); - ASSERT_TRUE(fetcher); - EXPECT_THAT(fetcher->GetOriginalURL().spec(), - testing::HasSubstr("/privet/v3/setup/start")); - fetcher->set_response_code(response_code); - scoped_refptr<net::HttpResponseHeaders> response_headers( - new net::HttpResponseHeaders("")); - response_headers->AddHeader("Content-Type: application/json"); - fetcher->set_response_headers(response_headers); - fetcher->SetResponseString(response); - fetcher->delegate()->OnURLFetchComplete(fetcher); - } - - net::TestURLFetcherFactory url_fetcher_factory_; - StrictMock<MockDelegate> delegate_; - PrivetV3SetupFlow setup_; - base::MessageLoop loop_; - base::RunLoop run_loop_; - base::Closure quit_closure_; -}; - -TEST_F(PrivetV3SetupFlowTest, InvalidTicket) { - EXPECT_CALL(delegate_, OnSetupError()).Times(1); - delegate_.gcd_server_response_ = "{}"; - setup_.Register(kServiceName); -} - -TEST_F(PrivetV3SetupFlowTest, InvalidDeviceResponse) { - EXPECT_CALL(delegate_, OnSetupError()).Times(1); - EXPECT_CALL(delegate_, ConfirmSecurityCode(_)) - .Times(1) - .WillOnce(WithArgs<0>(Invoke(this, &PrivetV3SetupFlowTest::ConfirmCode))); - delegate_.gcd_server_response_ = kRegistrationTicketResponse; - setup_.Register(kServiceName); - run_loop_.Run(); - SimulateFetch(0, "{}"); -} - -TEST_F(PrivetV3SetupFlowTest, Success) { - EXPECT_CALL(delegate_, OnSetupDone()).Times(1); - EXPECT_CALL(delegate_, ConfirmSecurityCode(_)) - .Times(1) - .WillOnce(WithArgs<0>(Invoke(this, &PrivetV3SetupFlowTest::ConfirmCode))); - delegate_.gcd_server_response_ = kRegistrationTicketResponse; - setup_.Register(kServiceName); - run_loop_.Run(); - SimulateFetch(200, "{}"); -} - -} // namespace - -} // namespace local_discovery
diff --git a/chrome/browser/local_discovery/privetv3_setup_operation.cc b/chrome/browser/local_discovery/privetv3_setup_operation.cc deleted file mode 100644 index a872675..0000000 --- a/chrome/browser/local_discovery/privetv3_setup_operation.cc +++ /dev/null
@@ -1,19 +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 "chrome/browser/local_discovery/privetv3_setup_operation.h" - -#include "base/logging.h" - -namespace local_discovery { - -scoped_ptr<PrivetV3SetupOperation> PrivetV3SetupOperation::Create( - PrivetV3Session* session, - const SetupStatusCallback& callback, - const std::string& ticket_id) { - NOTIMPLEMENTED(); - return scoped_ptr<PrivetV3SetupOperation>(); -} - -} // namespace local_discovery
diff --git a/chrome/browser/local_discovery/privetv3_setup_operation.h b/chrome/browser/local_discovery/privetv3_setup_operation.h deleted file mode 100644 index 39a6d12..0000000 --- a/chrome/browser/local_discovery/privetv3_setup_operation.h +++ /dev/null
@@ -1,37 +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 CHROME_BROWSER_LOCAL_DISCOVERY_PRIVETV3_SETUP_OPERATION_H_ -#define CHROME_BROWSER_LOCAL_DISCOVERY_PRIVETV3_SETUP_OPERATION_H_ - -#include <string> - -#include "base/callback.h" -#include "base/memory/scoped_ptr.h" - -namespace local_discovery { - -class PrivetV3Session; - -class PrivetV3SetupOperation { - public: - enum Status { STATUS_SUCCESS, STATUS_SETUP_ERROR, STATUS_SESSION_ERROR }; - - virtual ~PrivetV3SetupOperation() {} - - typedef base::Callback<void(Status status)> SetupStatusCallback; - - static scoped_ptr<PrivetV3SetupOperation> Create( - PrivetV3Session* session, - const SetupStatusCallback& callback, - const std::string& ticket_id); - - virtual void AddWifiCredentials(const std::string& ssid, - const std::string& passwd) = 0; - virtual void Start() = 0; -}; - -} // namespace local_discovery - -#endif // CHROME_BROWSER_LOCAL_DISCOVERY_PRIVETV3_SETUP_OPERATION_H_
diff --git a/chrome/browser/local_discovery/wifi/bootstrapping_device_lister.cc b/chrome/browser/local_discovery/wifi/bootstrapping_device_lister.cc deleted file mode 100644 index c8396e7..0000000 --- a/chrome/browser/local_discovery/wifi/bootstrapping_device_lister.cc +++ /dev/null
@@ -1,170 +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 "chrome/browser/local_discovery/wifi/bootstrapping_device_lister.h" - -#include <algorithm> -#include <iterator> - -#include "base/bind.h" -#include "base/location.h" -#include "base/message_loop/message_loop_proxy.h" -#include "base/stl_util.h" -#include "base/strings/string_util.h" - -namespace local_discovery { - -namespace wifi { - -namespace { - -const char kPrivetSuffix[] = "prv"; -// 3 for prv, 3 for type, one for connection status. -const size_t kPrivetCharactersAfterSeparator = 7; - -const struct { - const char* const short_name; - const char* const long_name; -} kPrivetShortNames[] = {{"cam", "camera"}, {"pri", "printer"}}; - -const struct { - char signifier; - BootstrappingDeviceDescription::ConnectionStatus status; -} kPrivetConnectionStatuses[] = { - {'C', BootstrappingDeviceDescription::CONNECTING}, - {'F', BootstrappingDeviceDescription::OFFLINE}, - {'L', BootstrappingDeviceDescription::LOCAL_ONLY}, - {'N', BootstrappingDeviceDescription::NOT_CONFIGURED}, - {'O', BootstrappingDeviceDescription::ONLINE}, -}; - -const char kPrivetDeviceLongName[] = "device"; - -std::string ExpandDeviceKind(const std::string& device_kind_short) { - for (size_t i = 0; i < arraysize(kPrivetShortNames); i++) { - if (device_kind_short == kPrivetShortNames[i].short_name) { - return kPrivetShortNames[i].long_name; - } - } - return kPrivetDeviceLongName; -} - -BootstrappingDeviceDescription::ConnectionStatus GetConnectionStatus( - char signifier) { - for (size_t i = 0; i < arraysize(kPrivetConnectionStatuses); i++) { - if (signifier == kPrivetConnectionStatuses[i].signifier) { - return kPrivetConnectionStatuses[i].status; - } - } - - LOG(WARNING) << "Unknown WiFi connection state signifier " << signifier; - return BootstrappingDeviceDescription::NOT_CONFIGURED; -} - -// Return true if the SSID is a privet ssid and fills |description| with its -// attributes. -bool ParsePrivetSSID(const std::string& internal_id, - const std::string& ssid, - BootstrappingDeviceDescription* description) { - if (!EndsWith(ssid, kPrivetSuffix, true)) - return false; - - size_t at_pos = ssid.length() - kPrivetCharactersAfterSeparator - 1; - - if (ssid[at_pos] != '@' || ssid.find('@', at_pos + 1) != std::string::npos) - return false; - - description->device_network_id = internal_id; - description->device_ssid = ssid; - - description->device_name = ssid.substr(0, at_pos); - description->device_kind = ExpandDeviceKind(ssid.substr(at_pos + 1, 3)); - description->connection_status = GetConnectionStatus(ssid.at(at_pos + 4)); - - return true; -} - -} // namespace - -BootstrappingDeviceDescription::BootstrappingDeviceDescription() - : connection_status(NOT_CONFIGURED) { -} - -BootstrappingDeviceDescription::~BootstrappingDeviceDescription() { -} - -BootstrappingDeviceLister::BootstrappingDeviceLister( - WifiManager* wifi_manager, - const UpdateCallback& update_callback) - : wifi_manager_(wifi_manager), - update_callback_(update_callback), - started_(false), - weak_factory_(this) { -} - -BootstrappingDeviceLister::~BootstrappingDeviceLister() { - if (started_) - wifi_manager_->RemoveNetworkListObserver(this); -} - -void BootstrappingDeviceLister::Start() { - DCHECK(!started_); - - started_ = true; - - wifi_manager_->AddNetworkListObserver(this); - - wifi_manager_->GetSSIDList( - base::Bind(&BootstrappingDeviceLister::OnNetworkListChanged, - weak_factory_.GetWeakPtr())); -} - -void BootstrappingDeviceLister::OnNetworkListChanged( - const std::vector<NetworkProperties>& ssids) { - ActiveDeviceList new_devices; - - for (size_t i = 0; i < ssids.size(); i++) { - new_devices.push_back(make_pair(ssids[i].ssid, ssids[i].guid)); - } - - std::sort(new_devices.begin(), new_devices.end()); - - base::WeakPtr<BootstrappingDeviceLister> weak_this = - weak_factory_.GetWeakPtr(); - // Find new or changed SSIDs - UpdateChangedSSIDs(true, new_devices, active_devices_); - if (!weak_this) - return; - - // Find removed SSIDs - UpdateChangedSSIDs(false, active_devices_, new_devices); - if (!weak_this) - return; - - active_devices_.swap(new_devices); -} - -void BootstrappingDeviceLister::UpdateChangedSSIDs( - bool available, - const ActiveDeviceList& changed, - const ActiveDeviceList& original) { - base::WeakPtr<BootstrappingDeviceLister> weak_this = - weak_factory_.GetWeakPtr(); - - ActiveDeviceList changed_devices = - base::STLSetDifference<ActiveDeviceList>(changed, original); - - for (ActiveDeviceList::reverse_iterator i = changed_devices.rbegin(); - weak_this && i != changed_devices.rend(); - i++) { - BootstrappingDeviceDescription description; - if (ParsePrivetSSID(i->second, i->first, &description)) { - update_callback_.Run(available, description); - } - } -} - -} // namespace wifi - -} // namespace local_discovery
diff --git a/chrome/browser/local_discovery/wifi/bootstrapping_device_lister.h b/chrome/browser/local_discovery/wifi/bootstrapping_device_lister.h deleted file mode 100644 index c2ca45e..0000000 --- a/chrome/browser/local_discovery/wifi/bootstrapping_device_lister.h +++ /dev/null
@@ -1,73 +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 CHROME_BROWSER_LOCAL_DISCOVERY_WIFI_BOOTSTRAPPING_DEVICE_LISTER_H_ -#define CHROME_BROWSER_LOCAL_DISCOVERY_WIFI_BOOTSTRAPPING_DEVICE_LISTER_H_ - -#include <vector> - -#include "base/callback.h" -#include "base/memory/weak_ptr.h" -#include "chrome/browser/local_discovery/wifi/wifi_manager.h" - -namespace local_discovery { - -namespace wifi { - -struct BootstrappingDeviceDescription { - enum ConnectionStatus { - ONLINE, - OFFLINE, - CONNECTING, - NOT_CONFIGURED, - LOCAL_ONLY - }; - - BootstrappingDeviceDescription(); - ~BootstrappingDeviceDescription(); - - std::string device_network_id; - std::string device_ssid; - std::string device_name; - std::string device_kind; - ConnectionStatus connection_status; -}; - -class BootstrappingDeviceLister : public NetworkListObserver { - public: - typedef base::Callback< - void(bool available, const BootstrappingDeviceDescription& description)> - UpdateCallback; - - BootstrappingDeviceLister(WifiManager* wifi_manager, - const UpdateCallback& update_callback); - ~BootstrappingDeviceLister() override; - - void Start(); - - private: - typedef std::vector< - std::pair<std::string /*ssid*/, std::string /*internal_name*/> > - ActiveDeviceList; - - void OnNetworkListChanged( - const std::vector<NetworkProperties>& ssids) override; - - void UpdateChangedSSIDs(bool available, - const ActiveDeviceList& changed, - const ActiveDeviceList& original); - - WifiManager* wifi_manager_; - UpdateCallback update_callback_; - - bool started_; - ActiveDeviceList active_devices_; - base::WeakPtrFactory<BootstrappingDeviceLister> weak_factory_; -}; - -} // namespace wifi - -} // namespace local_discovery - -#endif // CHROME_BROWSER_LOCAL_DISCOVERY_WIFI_BOOTSTRAPPING_DEVICE_LISTER_H_
diff --git a/chrome/browser/local_discovery/wifi/bootstrapping_device_lister_unittest.cc b/chrome/browser/local_discovery/wifi/bootstrapping_device_lister_unittest.cc deleted file mode 100644 index 1a02b92..0000000 --- a/chrome/browser/local_discovery/wifi/bootstrapping_device_lister_unittest.cc +++ /dev/null
@@ -1,205 +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 "base/bind.h" -#include "chrome/browser/local_discovery/wifi/bootstrapping_device_lister.h" -#include "chrome/browser/local_discovery/wifi/mock_wifi_manager.h" -#include "components/onc/onc_constants.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -using testing::StrictMock; -using testing::Mock; - -namespace local_discovery { - -namespace wifi { - -namespace { - -class MockableUpdateCallback { - public: - void UpdateCallback(bool available, - const BootstrappingDeviceDescription& description) { - UpdateCallbackInternal(available, - description.device_network_id, - description.device_ssid, - description.device_name, - description.device_kind, - description.connection_status); - } - - MOCK_METHOD6(UpdateCallbackInternal, - void(bool available, - const std::string& network_id, - const std::string& ssid, - const std::string& name, - const std::string& kind, - BootstrappingDeviceDescription::ConnectionStatus status)); - - BootstrappingDeviceLister::UpdateCallback callback() { - return base::Bind(&MockableUpdateCallback::UpdateCallback, - base::Unretained(this)); - } -}; - -class BootstrappingDeviceListerTest : public ::testing::Test { - public: - BootstrappingDeviceListerTest() - : lister_(&mock_wifi_manager_, mockable_callback_.callback()) {} - - ~BootstrappingDeviceListerTest() {} - - StrictMock<MockableUpdateCallback> mockable_callback_; - StrictMock<MockWifiManager> mock_wifi_manager_; - BootstrappingDeviceLister lister_; -}; - -TEST_F(BootstrappingDeviceListerTest, ListSingleDevice) { - EXPECT_CALL(mock_wifi_manager_, GetSSIDListInternal()); - lister_.Start(); - Mock::VerifyAndClearExpectations(&mock_wifi_manager_); - - std::vector<NetworkProperties> network_property_list; - - NetworkProperties network; - network.guid = "MyInternalID"; - network.ssid = "MyDevice@camNprv"; - network.connection_state = onc::connection_state::kNotConnected; - - network_property_list.push_back(network); - - NetworkProperties network2; - network2.guid = "MyInternalID2"; - network2.ssid = "SomeRandomNetwork"; - network2.connection_state = onc::connection_state::kNotConnected; - - network_property_list.push_back(network2); - - EXPECT_CALL( - mockable_callback_, - UpdateCallbackInternal(true, - "MyInternalID", - "MyDevice@camNprv", - "MyDevice", - "camera", - BootstrappingDeviceDescription::NOT_CONFIGURED)); - mock_wifi_manager_.CallSSIDListCallback(network_property_list); -} - -TEST_F(BootstrappingDeviceListerTest, AddRemoveDevice) { - EXPECT_CALL(mock_wifi_manager_, GetSSIDListInternal()); - lister_.Start(); - Mock::VerifyAndClearExpectations(&mock_wifi_manager_); - - std::vector<NetworkProperties> network_property_list; - - NetworkProperties network; - network.guid = "MyInternalID"; - network.ssid = "MyDevice@camNprv"; - network.connection_state = onc::connection_state::kNotConnected; - - network_property_list.push_back(network); - - std::vector<NetworkProperties> network_property_list2; - - NetworkProperties network2; - network2.guid = "MyInternalID2"; - network2.ssid = "MyDevice2@priFprv"; - network2.connection_state = onc::connection_state::kNotConnected; - - network_property_list2.push_back(network2); - - EXPECT_CALL( - mockable_callback_, - UpdateCallbackInternal(true, - "MyInternalID", - "MyDevice@camNprv", - "MyDevice", - "camera", - BootstrappingDeviceDescription::NOT_CONFIGURED)); - mock_wifi_manager_.CallSSIDListCallback(network_property_list); - - Mock::VerifyAndClearExpectations(&mock_wifi_manager_); - - EXPECT_CALL( - mockable_callback_, - UpdateCallbackInternal(false, - "MyInternalID", - "MyDevice@camNprv", - "MyDevice", - "camera", - BootstrappingDeviceDescription::NOT_CONFIGURED)); - EXPECT_CALL(mockable_callback_, - UpdateCallbackInternal(true, - "MyInternalID2", - "MyDevice2@priFprv", - "MyDevice2", - "printer", - BootstrappingDeviceDescription::OFFLINE)); - mock_wifi_manager_.CallNetworkListObservers(network_property_list2); -} - -TEST_F(BootstrappingDeviceListerTest, EdgeCases) { - EXPECT_CALL(mock_wifi_manager_, GetSSIDListInternal()); - lister_.Start(); - Mock::VerifyAndClearExpectations(&mock_wifi_manager_); - - std::vector<NetworkProperties> network_property_list; - - NetworkProperties network; - network.guid = "MyInternalID"; - network.ssid = "MyDevice@camprv"; - network.connection_state = onc::connection_state::kNotConnected; - - NetworkProperties network2; - network2.guid = "MyInternalID2"; - network2.ssid = "MyDevice2@unkNprv"; - network2.connection_state = onc::connection_state::kNotConnected; - - NetworkProperties network3; - network3.guid = "MyInternalID3"; - network3.ssid = "MyDevice3camNprv"; - network3.connection_state = onc::connection_state::kNotConnected; - - NetworkProperties network4; - network4.guid = "MyInternalID4"; - network4.ssid = "MyDevice4@camNnpr"; - network4.connection_state = onc::connection_state::kNotConnected; - - NetworkProperties network5; - network5.guid = "MyInternalID5"; - network5.ssid = "MyDevice5@With@At@Signs@camOprv"; - network5.connection_state = onc::connection_state::kNotConnected; - - network_property_list.push_back(network); - network_property_list.push_back(network2); - network_property_list.push_back(network3); - network_property_list.push_back(network4); - network_property_list.push_back(network5); - - EXPECT_CALL( - mockable_callback_, - UpdateCallbackInternal(true, - "MyInternalID2", - "MyDevice2@unkNprv", - "MyDevice2", - "device", - BootstrappingDeviceDescription::NOT_CONFIGURED)); - - EXPECT_CALL(mockable_callback_, - UpdateCallbackInternal(true, - "MyInternalID5", - "MyDevice5@With@At@Signs@camOprv", - "MyDevice5@With@At@Signs", - "camera", - BootstrappingDeviceDescription::ONLINE)); - mock_wifi_manager_.CallSSIDListCallback(network_property_list); -} - -} // namespace - -} // namespace wifi - -} // namespace local_discovery
diff --git a/chrome/browser/local_discovery/wifi/bootstrapping_network_switcher.cc b/chrome/browser/local_discovery/wifi/bootstrapping_network_switcher.cc deleted file mode 100644 index f99adea..0000000 --- a/chrome/browser/local_discovery/wifi/bootstrapping_network_switcher.cc +++ /dev/null
@@ -1,72 +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 "chrome/browser/local_discovery/wifi/bootstrapping_network_switcher.h" - -#include "base/bind.h" -#include "components/onc/onc_constants.h" - -namespace local_discovery { - -namespace wifi { - -BootstrappingNetworkSwitcher::BootstrappingNetworkSwitcher( - WifiManager* wifi_manager, - const std::string& connect_ssid, - const SuccessCallback& callback) - : wifi_manager_(wifi_manager), - connect_ssid_(connect_ssid), - callback_(callback), - connected_(false), - weak_factory_(this) { -} - -BootstrappingNetworkSwitcher::~BootstrappingNetworkSwitcher() { - Disconnect(); -} - -void BootstrappingNetworkSwitcher::Connect() { - wifi_manager_->GetSSIDList( - base::Bind(&BootstrappingNetworkSwitcher::OnGotNetworkList, - weak_factory_.GetWeakPtr())); -} - -void BootstrappingNetworkSwitcher::Disconnect() { - if (connected_ && !return_guid_.empty()) { - connected_ = false; - wifi_manager_->ConnectToNetworkByID(return_guid_, - WifiManager::SuccessCallback()); - } -} - -void BootstrappingNetworkSwitcher::OnGotNetworkList( - const NetworkPropertiesList& networks) { - for (NetworkPropertiesList::const_iterator i = networks.begin(); - i != networks.end(); - i++) { - if (i->connection_state == onc::connection_state::kConnected) { - return_guid_ = i->guid; - break; - } - } - - // We are "connected" while attempting to connect even if we fail - connected_ = true; - - // Bootstrapping devices should have an empty PSK. - wifi_manager_->ConfigureAndConnectNetwork( - connect_ssid_, - WifiCredentials::FromPSK(std::string()), - base::Bind(&BootstrappingNetworkSwitcher::OnConnectStatus, - weak_factory_.GetWeakPtr())); -} - -void BootstrappingNetworkSwitcher::OnConnectStatus(bool status) { - connected_ = status; - callback_.Run(status); -} - -} // namespace wifi - -} // namespace local_discovery
diff --git a/chrome/browser/local_discovery/wifi/bootstrapping_network_switcher.h b/chrome/browser/local_discovery/wifi/bootstrapping_network_switcher.h deleted file mode 100644 index ca660b0..0000000 --- a/chrome/browser/local_discovery/wifi/bootstrapping_network_switcher.h +++ /dev/null
@@ -1,50 +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 CHROME_BROWSER_LOCAL_DISCOVERY_WIFI_BOOTSTRAPPING_NETWORK_SWITCHER_H_ -#define CHROME_BROWSER_LOCAL_DISCOVERY_WIFI_BOOTSTRAPPING_NETWORK_SWITCHER_H_ - -#include <string> - -#include "base/callback.h" -#include "base/memory/weak_ptr.h" -#include "chrome/browser/local_discovery/wifi/wifi_manager.h" - -namespace local_discovery { - -namespace wifi { - -class BootstrappingNetworkSwitcher { - public: - typedef base::Callback<void(bool success)> SuccessCallback; - - BootstrappingNetworkSwitcher(WifiManager* wifi_manager, - const std::string& connect_ssid, - const SuccessCallback& callback); - ~BootstrappingNetworkSwitcher(); - - void Connect(); - - void Disconnect(); - - private: - void OnGotNetworkList(const NetworkPropertiesList& networks); - - void OnConnectStatus(bool status); - - WifiManager* wifi_manager_; - std::string connect_ssid_; - SuccessCallback callback_; - - std::string return_guid_; - bool connected_; - - base::WeakPtrFactory<BootstrappingNetworkSwitcher> weak_factory_; -}; - -} // namespace wifi - -} // namespace local_discovery - -#endif // CHROME_BROWSER_LOCAL_DISCOVERY_WIFI_BOOTSTRAPPING_NETWORK_SWITCHER_H_
diff --git a/chrome/browser/local_discovery/wifi/bootstrapping_network_switcher_unittest.cc b/chrome/browser/local_discovery/wifi/bootstrapping_network_switcher_unittest.cc deleted file mode 100644 index 4c3a6d8..0000000 --- a/chrome/browser/local_discovery/wifi/bootstrapping_network_switcher_unittest.cc +++ /dev/null
@@ -1,124 +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 "base/bind.h" -#include "chrome/browser/local_discovery/wifi/bootstrapping_network_switcher.h" -#include "chrome/browser/local_discovery/wifi/mock_wifi_manager.h" -#include "components/onc/onc_constants.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -using testing::StrictMock; - -namespace local_discovery { - -namespace wifi { - -namespace { - -class MockableNetworkSwitchCallback { - public: - MOCK_METHOD1(OnNetworkSwitch, void(bool success)); - - BootstrappingNetworkSwitcher::SuccessCallback callback() { - return base::Bind(&MockableNetworkSwitchCallback::OnNetworkSwitch, - base::Unretained(this)); - } -}; - -class BootstrappingNetworkSwitcherTest : public ::testing::Test { - public: - BootstrappingNetworkSwitcherTest() { - NetworkProperties network1; - network1.guid = "SampleGUID1"; - network1.ssid = "SampleSSID1"; - network1.connection_state = onc::connection_state::kNotConnected; - - NetworkProperties network2; - network2.guid = "SampleGUID2"; - network2.ssid = "SampleSSID2"; - network2.connection_state = onc::connection_state::kConnected; - - network_properties_.push_back(network1); - network_properties_.push_back(network2); - } - - ~BootstrappingNetworkSwitcherTest() {} - - NetworkPropertiesList network_properties_; - StrictMock<MockableNetworkSwitchCallback> mockable_callback_; - StrictMock<MockWifiManager> mock_wifi_manager_; - scoped_ptr<BootstrappingNetworkSwitcher> network_switcher_; -}; - -TEST_F(BootstrappingNetworkSwitcherTest, EndToEndSuccess) { - network_switcher_.reset(new BootstrappingNetworkSwitcher( - &mock_wifi_manager_, "SampleConnectSSID", mockable_callback_.callback())); - - EXPECT_CALL(mock_wifi_manager_, GetSSIDListInternal()); - network_switcher_->Connect(); - - EXPECT_CALL(mock_wifi_manager_, - ConfigureAndConnectNetworkInternal("SampleConnectSSID", "")); - mock_wifi_manager_.CallSSIDListCallback(network_properties_); - - EXPECT_CALL(mockable_callback_, OnNetworkSwitch(true)); - mock_wifi_manager_.CallConfigureAndConnectNetworkCallback(true); - - EXPECT_CALL(mock_wifi_manager_, ConnectToNetworkByIDInternal("SampleGUID2")); - network_switcher_->Disconnect(); -} - -TEST_F(BootstrappingNetworkSwitcherTest, MidconnnectCancel) { - network_switcher_.reset(new BootstrappingNetworkSwitcher( - &mock_wifi_manager_, "SampleConnectSSID", mockable_callback_.callback())); - - EXPECT_CALL(mock_wifi_manager_, GetSSIDListInternal()); - network_switcher_->Connect(); - - EXPECT_CALL(mock_wifi_manager_, - ConfigureAndConnectNetworkInternal("SampleConnectSSID", "")); - mock_wifi_manager_.CallSSIDListCallback(network_properties_); - - EXPECT_CALL(mock_wifi_manager_, ConnectToNetworkByIDInternal("SampleGUID2")); - network_switcher_->Disconnect(); -} - -TEST_F(BootstrappingNetworkSwitcherTest, Failure) { - network_switcher_.reset(new BootstrappingNetworkSwitcher( - &mock_wifi_manager_, "SampleConnectSSID", mockable_callback_.callback())); - - EXPECT_CALL(mock_wifi_manager_, GetSSIDListInternal()); - network_switcher_->Connect(); - - EXPECT_CALL(mock_wifi_manager_, - ConfigureAndConnectNetworkInternal("SampleConnectSSID", "")); - mock_wifi_manager_.CallSSIDListCallback(network_properties_); - - EXPECT_CALL(mockable_callback_, OnNetworkSwitch(false)); - mock_wifi_manager_.CallConfigureAndConnectNetworkCallback(false); - - network_switcher_->Disconnect(); -} - -TEST_F(BootstrappingNetworkSwitcherTest, RAII) { - network_switcher_.reset(new BootstrappingNetworkSwitcher( - &mock_wifi_manager_, "SampleConnectSSID", mockable_callback_.callback())); - - EXPECT_CALL(mock_wifi_manager_, GetSSIDListInternal()); - network_switcher_->Connect(); - - EXPECT_CALL(mock_wifi_manager_, - ConfigureAndConnectNetworkInternal("SampleConnectSSID", "")); - mock_wifi_manager_.CallSSIDListCallback(network_properties_); - - EXPECT_CALL(mock_wifi_manager_, ConnectToNetworkByIDInternal("SampleGUID2")); - network_switcher_.reset(); -} - -} // namespace - -} // namespace wifi - -} // namespace local_discovery
diff --git a/chrome/browser/media/chrome_webrtc_apprtc_browsertest.cc b/chrome/browser/media/chrome_webrtc_apprtc_browsertest.cc index f494e79..6eada11a 100644 --- a/chrome/browser/media/chrome_webrtc_apprtc_browsertest.cc +++ b/chrome/browser/media/chrome_webrtc_apprtc_browsertest.cc
@@ -55,10 +55,8 @@ void SetUpCommandLine(base::CommandLine* command_line) override { EXPECT_FALSE(command_line->HasSwitch(switches::kUseFakeUIForMediaStream)); - // The video playback will not work without a GPU, so force its use here. - command_line->AppendSwitch(switches::kUseGpuInTests); - base::CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kUseFakeDeviceForMediaStream); + // Use fake devices in order to run on VMs. + command_line->AppendSwitch(switches::kUseFakeDeviceForMediaStream); } void TearDown() override {
diff --git a/chrome/browser/media/chrome_webrtc_simulcast_browsertest.cc b/chrome/browser/media/chrome_webrtc_simulcast_browsertest.cc new file mode 100644 index 0000000..5fd918a --- /dev/null +++ b/chrome/browser/media/chrome_webrtc_simulcast_browsertest.cc
@@ -0,0 +1,54 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/command_line.h" +#include "base/files/file_path.h" +#include "base/path_service.h" +#include "chrome/browser/media/webrtc_browsertest_base.h" +#include "chrome/browser/media/webrtc_browsertest_common.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_tabstrip.h" +#include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/ui_test_utils.h" +#include "content/public/browser/notification_service.h" +#include "content/public/browser/render_process_host.h" +#include "content/public/test/browser_test_utils.h" +#include "media/base/media_switches.h" +#include "net/test/embedded_test_server/embedded_test_server.h" +#include "testing/perf/perf_test.h" +#include "ui/gl/gl_switches.h" + +static const char kSimulcastTestPage[] = "/webrtc/webrtc-simulcast.html"; + +// Simulcast integration test. This test ensures 'a=x-google-flag:conference' +// is working and that Chrome is capable of sending simulcast streams. To run +// this test, Chrome must be hideout-enabled. +class WebRtcSimulcastBrowserTest : public WebRtcTestBase { + public: + // TODO(phoglund): Make it possible to enable DetectErrorsInJavaScript() here. + + void SetUpCommandLine(base::CommandLine* command_line) override { + // Just answer 'allow' to GetUserMedia invocations. + command_line->AppendSwitch(switches::kUseFakeUIForMediaStream); + + // Use fake devices in order to run on VMs. + command_line->AppendSwitch(switches::kUseFakeDeviceForMediaStream); + } +}; + +IN_PROC_BROWSER_TEST_F(WebRtcSimulcastBrowserTest, + TestVgaReturnsTwoSimulcastStreams) { + ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); + + ui_test_utils::NavigateToURL( + browser(), embedded_test_server()->GetURL(kSimulcastTestPage)); + + content::WebContents* tab_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + + ASSERT_EQ("OK", ExecuteJavascript("testVgaReturnsTwoSimulcastStreams()", + tab_contents)); +}
diff --git a/chrome/browser/media/chrome_webrtc_video_quality_browsertest.cc b/chrome/browser/media/chrome_webrtc_video_quality_browsertest.cc index 7d1347e..6c88d95 100644 --- a/chrome/browser/media/chrome_webrtc_video_quality_browsertest.cc +++ b/chrome/browser/media/chrome_webrtc_video_quality_browsertest.cc
@@ -116,9 +116,6 @@ command_line->AppendSwitchPath(switches::kUseFileForFakeVideoCapture, webrtc_reference_video_y4m_); command_line->AppendSwitch(switches::kUseFakeDeviceForMediaStream); - - // The video playback will not work without a GPU, so force its use here. - command_line->AppendSwitch(switches::kUseGpuInTests); } // Writes all frames we've captured so far by grabbing them from the
diff --git a/chrome/browser/media/encrypted_media_browsertest.cc b/chrome/browser/media/encrypted_media_browsertest.cc index 38362afa..771eeae 100644 --- a/chrome/browser/media/encrypted_media_browsertest.cc +++ b/chrome/browser/media/encrypted_media_browsertest.cc
@@ -337,13 +337,13 @@ // Tests encrypted media playback using ExternalClearKey key system in // decrypt-and-decode mode for unprefixed EME. -// TODO(jrummell): Merge with ECKEncryptedMediaTest once unprefixed is -// enabled by default. +// TODO(jrummell): Make ECKEncryptedMediaTest run the unprefixed tests and add +// a prefixed class to run the prefixed tests. (Once prefixed is disabled by +// default, we will need a subclass to enable it from the command line.) class ECKUnprefixedEncryptedMediaTest : public EncryptedMediaTestBase { protected: void SetUpCommandLine(base::CommandLine* command_line) override { EncryptedMediaTestBase::SetUpCommandLine(command_line); - command_line->AppendSwitch(switches::kEnableEncryptedMedia); SetUpCommandLineForKeySystem(kExternalClearKeyKeySystem, command_line); } }; @@ -354,7 +354,6 @@ protected: void SetUpCommandLine(base::CommandLine* command_line) override { EncryptedMediaTestBase::SetUpCommandLine(command_line); - command_line->AppendSwitch(switches::kEnableEncryptedMedia); SetUpCommandLineForKeySystem(kWidevineKeySystem, command_line); } }; @@ -437,9 +436,6 @@ void SetUpCommandLine(base::CommandLine* command_line) override { EncryptedMediaTestBase::SetUpCommandLine(command_line); SetUpCommandLineForKeySystem(CurrentKeySystem(), command_line); - - if (CurrentEmeVersion() == UNPREFIXED) - command_line->AppendSwitch(switches::kEnableEncryptedMedia); } };
diff --git a/chrome/browser/media_galleries/fileapi/device_media_async_file_util.cc b/chrome/browser/media_galleries/fileapi/device_media_async_file_util.cc index dce3a583..1cacf71 100644 --- a/chrome/browser/media_galleries/fileapi/device_media_async_file_util.cc +++ b/chrome/browser/media_galleries/fileapi/device_media_async_file_util.cc
@@ -16,11 +16,11 @@ #include "chrome/browser/media_galleries/fileapi/readahead_file_stream_reader.h" #include "content/public/browser/browser_thread.h" #include "storage/browser/blob/file_stream_reader.h" +#include "storage/browser/blob/shareable_file_reference.h" #include "storage/browser/fileapi/file_system_context.h" #include "storage/browser/fileapi/file_system_operation_context.h" #include "storage/browser/fileapi/file_system_url.h" #include "storage/browser/fileapi/native_file_util.h" -#include "storage/common/blob/shareable_file_reference.h" using storage::AsyncFileUtil; using storage::FileSystemOperationContext;
diff --git a/chrome/browser/media_galleries/fileapi/device_media_async_file_util.h b/chrome/browser/media_galleries/fileapi/device_media_async_file_util.h index ebfd6b8..3716c44 100644 --- a/chrome/browser/media_galleries/fileapi/device_media_async_file_util.h +++ b/chrome/browser/media_galleries/fileapi/device_media_async_file_util.h
@@ -10,8 +10,8 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" +#include "storage/browser/blob/shareable_file_reference.h" #include "storage/browser/fileapi/async_file_util.h" -#include "storage/common/blob/shareable_file_reference.h" namespace storage { class FileSystemOperationContext;
diff --git a/chrome/browser/media_galleries/fileapi/iphoto_file_util.cc b/chrome/browser/media_galleries/fileapi/iphoto_file_util.cc index ab47add..317d19fe 100644 --- a/chrome/browser/media_galleries/fileapi/iphoto_file_util.cc +++ b/chrome/browser/media_galleries/fileapi/iphoto_file_util.cc
@@ -16,10 +16,10 @@ #include "chrome/browser/media_galleries/fileapi/media_path_filter.h" #include "chrome/browser/media_galleries/imported_media_gallery_registry.h" #include "content/public/browser/browser_thread.h" +#include "storage/browser/blob/shareable_file_reference.h" #include "storage/browser/fileapi/file_system_operation_context.h" #include "storage/browser/fileapi/file_system_url.h" #include "storage/browser/fileapi/native_file_util.h" -#include "storage/common/blob/shareable_file_reference.h" #include "storage/common/fileapi/directory_entry.h" #include "storage/common/fileapi/file_system_util.h"
diff --git a/chrome/browser/media_galleries/fileapi/itunes_file_util.cc b/chrome/browser/media_galleries/fileapi/itunes_file_util.cc index 41185ee..add9982 100644 --- a/chrome/browser/media_galleries/fileapi/itunes_file_util.cc +++ b/chrome/browser/media_galleries/fileapi/itunes_file_util.cc
@@ -15,10 +15,10 @@ #include "chrome/browser/media_galleries/fileapi/media_path_filter.h" #include "chrome/browser/media_galleries/imported_media_gallery_registry.h" #include "content/public/browser/browser_thread.h" +#include "storage/browser/blob/shareable_file_reference.h" #include "storage/browser/fileapi/file_system_operation_context.h" #include "storage/browser/fileapi/file_system_url.h" #include "storage/browser/fileapi/native_file_util.h" -#include "storage/common/blob/shareable_file_reference.h" #include "storage/common/fileapi/file_system_util.h" using storage::DirectoryEntry;
diff --git a/chrome/browser/media_galleries/fileapi/native_media_file_util.cc b/chrome/browser/media_galleries/fileapi/native_media_file_util.cc index 9d7d362d..9584bed 100644 --- a/chrome/browser/media_galleries/fileapi/native_media_file_util.cc +++ b/chrome/browser/media_galleries/fileapi/native_media_file_util.cc
@@ -16,10 +16,10 @@ #include "content/public/browser/browser_thread.h" #include "net/base/io_buffer.h" #include "net/base/mime_sniffer.h" +#include "storage/browser/blob/shareable_file_reference.h" #include "storage/browser/fileapi/file_system_context.h" #include "storage/browser/fileapi/file_system_operation_context.h" #include "storage/browser/fileapi/native_file_util.h" -#include "storage/common/blob/shareable_file_reference.h" #include "url/gurl.h" namespace {
diff --git a/chrome/browser/media_galleries/fileapi/picasa_file_util_unittest.cc b/chrome/browser/media_galleries/fileapi/picasa_file_util_unittest.cc index 9171151..d7f532a5 100644 --- a/chrome/browser/media_galleries/fileapi/picasa_file_util_unittest.cc +++ b/chrome/browser/media_galleries/fileapi/picasa_file_util_unittest.cc
@@ -28,13 +28,13 @@ #include "content/public/test/mock_special_storage_policy.h" #include "content/public/test/test_browser_thread.h" #include "content/public/test/test_file_system_options.h" +#include "storage/browser/blob/shareable_file_reference.h" #include "storage/browser/fileapi/async_file_util.h" #include "storage/browser/fileapi/external_mount_points.h" #include "storage/browser/fileapi/file_system_context.h" #include "storage/browser/fileapi/file_system_operation_context.h" #include "storage/browser/fileapi/file_system_operation_runner.h" #include "storage/browser/fileapi/isolated_context.h" -#include "storage/common/blob/shareable_file_reference.h" #include "testing/gtest/include/gtest/gtest.h" using storage::FileSystemOperationContext;
diff --git a/chrome/browser/memory_details_mac.cc b/chrome/browser/memory_details_mac.cc index efee359a..1e68c0a 100644 --- a/chrome/browser/memory_details_mac.cc +++ b/chrome/browser/memory_details_mac.cc
@@ -80,7 +80,7 @@ scoped_ptr<base::ProcessMetrics> metrics; metrics.reset(base::ProcessMetrics::CreateProcessMetrics( pid, content::BrowserChildProcessHost::GetPortProvider())); - metrics->GetWorkingSetKBytes(&info.working_set); + metrics->GetCommittedAndWorkingSetKBytes(&info.committed, &info.working_set); processes->push_back(info); }
diff --git a/chrome/browser/metrics/chrome_metrics_service_client.cc b/chrome/browser/metrics/chrome_metrics_service_client.cc index 7bfc739..5d30941 100644 --- a/chrome/browser/metrics/chrome_metrics_service_client.cc +++ b/chrome/browser/metrics/chrome_metrics_service_client.cc
@@ -296,10 +296,19 @@ metrics_service_->RegisterMetricsProvider( scoped_ptr<metrics::MetricsProvider>(google_update_metrics_provider_)); + // Report exit funnels for canary and dev only. + bool report_exit_funnels = false; + switch (chrome::VersionInfo::GetChannel()) { + case chrome::VersionInfo::CHANNEL_CANARY: + case chrome::VersionInfo::CHANNEL_DEV: + report_exit_funnels = true; + break; + } + metrics_service_->RegisterMetricsProvider( scoped_ptr<metrics::MetricsProvider>( new browser_watcher::WatcherMetricsProviderWin( - chrome::kBrowserExitCodesRegistryPath))); + chrome::kBrowserExitCodesRegistryPath, report_exit_funnels))); #endif // defined(OS_WIN) #if defined(ENABLE_PLUGINS)
diff --git a/chrome/browser/net/crl_set_fetcher.cc b/chrome/browser/net/crl_set_fetcher.cc index 14841e94..fba9da6 100644 --- a/chrome/browser/net/crl_set_fetcher.cc +++ b/chrome/browser/net/crl_set_fetcher.cc
@@ -15,6 +15,7 @@ #include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_paths.h" #include "components/component_updater/component_updater_service.h" +#include "components/update_client/update_client.h" #include "content/public/browser/browser_thread.h" #include "net/cert/crl_set.h" #include "net/cert/crl_set_storage.h" @@ -138,7 +139,7 @@ void CRLSetFetcher::RegisterComponent(uint32 sequence_of_loaded_crl) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - component_updater::CrxComponent component; + update_client::CrxComponent component; component.pk_hash.assign(kPublicKeySHA256, kPublicKeySHA256 + sizeof(kPublicKeySHA256)); component.installer = this;
diff --git a/chrome/browser/net/crl_set_fetcher.h b/chrome/browser/net/crl_set_fetcher.h index d6e74d7..3568df3 100644 --- a/chrome/browser/net/crl_set_fetcher.h +++ b/chrome/browser/net/crl_set_fetcher.h
@@ -10,7 +10,7 @@ #include "base/compiler_specific.h" #include "base/files/file_path.h" #include "base/memory/ref_counted.h" -#include "components/component_updater/component_updater_service.h" +#include "components/update_client/update_client.h" namespace base { class DictionaryValue; @@ -21,7 +21,11 @@ class CRLSet; } -class CRLSetFetcher : public component_updater::ComponentInstaller, +namespace component_updater { +class ComponentUpdateService; +} + +class CRLSetFetcher : public update_client::ComponentInstaller, public base::RefCountedThreadSafe<CRLSetFetcher> { public: CRLSetFetcher();
diff --git a/chrome/browser/net/network_stats.cc b/chrome/browser/net/network_stats.cc index 388f5c6..51df4c2 100644 --- a/chrome/browser/net/network_stats.cc +++ b/chrome/browser/net/network_stats.cc
@@ -417,8 +417,6 @@ TestType test_type = test_sequence_[current_test_index_]; uint32 received_packets = packets_received_mask_.count(); - // Now() has resolution ~1-15ms. HighResNow() has high resolution but it - // is warned not to use it unless necessary. base::TimeTicks current_time = base::TimeTicks::Now(); last_arrival_time_ = current_time; if (first_arrival_time_.is_null())
diff --git a/chrome/browser/net/predictor.cc b/chrome/browser/net/predictor.cc index b3da9541..dabea06c 100644 --- a/chrome/browser/net/predictor.cc +++ b/chrome/browser/net/predictor.cc
@@ -43,6 +43,8 @@ #include "net/dns/host_resolver.h" #include "net/dns/single_request_host_resolver.h" #include "net/http/transport_security_state.h" +#include "net/proxy/proxy_info.h" +#include "net/proxy/proxy_service.h" #include "net/ssl/ssl_config_service.h" #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_context_getter.h"
diff --git a/chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_io_data.cc b/chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_io_data.cc new file mode 100644 index 0000000..81b669f --- /dev/null +++ b/chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_io_data.cc
@@ -0,0 +1,66 @@ +// Copyright 2015 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/net/spdyproxy/data_reduction_proxy_chrome_io_data.h" + +#include "base/bind.h" +#include "base/prefs/pref_service.h" +#include "base/time/time.h" +#include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings.h" +#include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings_factory.h" +#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.h" +#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h" +#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_statistics_prefs.h" +#include "components/data_reduction_proxy/core/common/data_reduction_proxy_event_store.h" + +namespace content { +class BrowserContext; +} + +scoped_ptr<data_reduction_proxy::DataReductionProxyIOData> +CreateDataReductionProxyChromeIOData( + net::NetLog* net_log, + content::BrowserContext* browser_context, + PrefService* prefs, + const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner, + const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner) { + DCHECK(net_log); + DCHECK(prefs); + DCHECK(browser_context); + DataReductionProxyChromeSettings* settings = + DataReductionProxyChromeSettingsFactory::GetForBrowserContext( + browser_context); + +#if defined(OS_ANDROID) || defined(OS_IOS) + // On mobile we write data reduction proxy prefs directly to the pref service. + // On desktop we store data reduction proxy prefs in memory, writing to disk + // every 60 minutes and on termination. Shutdown hooks must be added for + // Android and iOS in order for non-zero delays to be supported. + // (http://crbug.com/408264) + base::TimeDelta commit_delay = base::TimeDelta(); +#else + base::TimeDelta commit_delay = base::TimeDelta::FromMinutes(60); +#endif + + data_reduction_proxy::DataReductionProxyStatisticsPrefs* + data_reduction_proxy_statistics_prefs = + new data_reduction_proxy::DataReductionProxyStatisticsPrefs( + prefs, ui_task_runner, + commit_delay); + + scoped_ptr<data_reduction_proxy::DataReductionProxyIOData> + data_reduction_proxy_io_data( + new data_reduction_proxy::DataReductionProxyIOData( + DataReductionProxyChromeSettings::GetClient(), + make_scoped_ptr(data_reduction_proxy_statistics_prefs), + settings, + net_log, + io_task_runner, + ui_task_runner)); + data_reduction_proxy_io_data->InitOnUIThread(prefs); + settings->SetDataReductionProxyStatisticsPrefs( + data_reduction_proxy_statistics_prefs); + + return data_reduction_proxy_io_data.Pass(); +}
diff --git a/chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_io_data.h b/chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_io_data.h new file mode 100644 index 0000000..f60240c --- /dev/null +++ b/chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_io_data.h
@@ -0,0 +1,42 @@ +// Copyright 2015 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_NET_SPDYPROXY_DATA_REDUCTION_PROXY_CHROME_IO_DATA_H_ +#define CHROME_BROWSER_NET_SPDYPROXY_DATA_REDUCTION_PROXY_CHROME_IO_DATA_H_ + +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" + +class DataReductionProxyChromeConfigurator; +class PrefService; + +namespace base { +class SingleThreadTaskRunner; +} + +namespace content { +class BrowserContext; +} + +namespace data_reduction_proxy { +class DataReductionProxyConfigurator; +class DataReductionProxyIOData; +class DataReductionProxySettings; +} + +namespace net { +class NetLog; +} + +// Constructs DataReductionProxyIOData suitable for use by ProfileImpl and +// ProfileImplIOData. +scoped_ptr<data_reduction_proxy::DataReductionProxyIOData> +CreateDataReductionProxyChromeIOData( + net::NetLog* net_log, + content::BrowserContext* browser_context, + PrefService* prefs, + const scoped_refptr<base::SingleThreadTaskRunner>& io_thread_runner, + const scoped_refptr<base::SingleThreadTaskRunner>& ui_thread_runner); + +#endif // CHROME_BROWSER_NET_SPDYPROXY_DATA_REDUCTION_PROXY_CHROME_IO_DATA_H_
diff --git a/chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings.cc b/chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings.cc index 9598d7d..65607f3 100644 --- a/chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings.cc +++ b/chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings.cc
@@ -15,6 +15,7 @@ #include "chrome/common/pref_names.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_auth_request_handler.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.h" +#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h" #include "net/url_request/url_request_context_getter.h" @@ -58,18 +59,16 @@ } void DataReductionProxyChromeSettings::InitDataReductionProxySettings( - data_reduction_proxy::DataReductionProxyConfigurator* configurator, + data_reduction_proxy::DataReductionProxyIOData* io_data, PrefService* profile_prefs, PrefService* local_state_prefs, - net::URLRequestContextGetter* request_context, - net::NetLog* net_log, - data_reduction_proxy::DataReductionProxyEventStore* event_store) { - SetProxyConfigurator(configurator); + net::URLRequestContextGetter* request_context) { + SetProxyConfigurator(io_data->configurator()); DataReductionProxySettings::InitDataReductionProxySettings( profile_prefs, request_context, - net_log, - event_store); + io_data->net_log(), + io_data->event_store()); DataReductionProxySettings::SetOnDataReductionEnabledCallback( base::Bind(&DataReductionProxyChromeSettings::RegisterSyntheticFieldTrial, base::Unretained(this)));
diff --git a/chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings.h b/chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings.h index 92130cb..d77d0fd0 100644 --- a/chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings.h +++ b/chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings.h
@@ -16,6 +16,7 @@ namespace data_reduction_proxy { class DataReductionProxyConfigurator; +class DataReductionProxyIOData; class DataReductionProxyEventStore; class DataReductionProxyParams; } @@ -44,12 +45,10 @@ // Initialize the settings object with the given configurator, prefs services, // and request context. void InitDataReductionProxySettings( - data_reduction_proxy::DataReductionProxyConfigurator* configurator, + data_reduction_proxy::DataReductionProxyIOData* io_data, PrefService* profile_prefs, PrefService* local_state_prefs, - net::URLRequestContextGetter* request_context, - net::NetLog* net_log, - data_reduction_proxy::DataReductionProxyEventStore* event_store); + net::URLRequestContextGetter* request_context); // Gets the client type for the data reduction proxy. static data_reduction_proxy::Client GetClient();
diff --git a/chrome/browser/notifications/extension_welcome_notification_unittest.cc b/chrome/browser/notifications/extension_welcome_notification_unittest.cc index ce5c40f..9d22026 100644 --- a/chrome/browser/notifications/extension_welcome_notification_unittest.cc +++ b/chrome/browser/notifications/extension_welcome_notification_unittest.cc
@@ -224,7 +224,6 @@ base::UTF8ToUTF16("Title"), base::UTF8ToUTF16("Body"), gfx::Image(), - blink::WebTextDirectionDefault, notifier_id, base::UTF8ToUTF16("Source"), base::UTF8ToUTF16(notification_id),
diff --git a/chrome/browser/notifications/message_center_notifications_browsertest.cc b/chrome/browser/notifications/message_center_notifications_browsertest.cc index 52f9949..882df3f1 100644 --- a/chrome/browser/notifications/message_center_notifications_browsertest.cc +++ b/chrome/browser/notifications/message_center_notifications_browsertest.cc
@@ -126,7 +126,6 @@ base::ASCIIToUTF16("title"), base::ASCIIToUTF16("message"), gfx::Image(), - blink::WebTextDirectionDefault, message_center::NotifierId( message_center::NotifierId::APPLICATION, "extension_id"),
diff --git a/chrome/browser/notifications/message_center_settings_controller_unittest.cc b/chrome/browser/notifications/message_center_settings_controller_unittest.cc index ddc86ca..4b44208 100644 --- a/chrome/browser/notifications/message_center_settings_controller_unittest.cc +++ b/chrome/browser/notifications/message_center_settings_controller_unittest.cc
@@ -83,7 +83,7 @@ MessageCenterSettingsControllerBaseTest::TearDown(); } - virtual TestingProfile* CreateProfile(const std::string& name) override { + TestingProfile* CreateProfile(const std::string& name) override { TestingProfile* profile = MessageCenterSettingsControllerBaseTest::CreateProfile(name);
diff --git a/chrome/browser/notifications/notification.cc b/chrome/browser/notifications/notification.cc index d182c6b..922f6b6 100644 --- a/chrome/browser/notifications/notification.cc +++ b/chrome/browser/notifications/notification.cc
@@ -30,7 +30,6 @@ const base::string16& title, const base::string16& body, const gfx::Image& icon, - blink::WebTextDirection dir, const message_center::NotifierId& notifier_id, const base::string16& display_source, const base::string16& replace_id,
diff --git a/chrome/browser/notifications/notification.h b/chrome/browser/notifications/notification.h index 363ece7..f2afac4 100644 --- a/chrome/browser/notifications/notification.h +++ b/chrome/browser/notifications/notification.h
@@ -12,7 +12,6 @@ #include "base/strings/string16.h" #include "base/values.h" #include "chrome/browser/notifications/notification_delegate.h" -#include "third_party/WebKit/public/web/WebTextDirection.h" #include "ui/message_center/notification.h" #include "ui/message_center/notification_types.h" #include "url/gurl.h" @@ -38,7 +37,6 @@ const base::string16& title, const base::string16& body, const gfx::Image& icon, - blink::WebTextDirection dir, const message_center::NotifierId& notifier_id, const base::string16& display_source, const base::string16& replace_id,
diff --git a/chrome/browser/notifications/notification_conversion_helper_unittest.cc b/chrome/browser/notifications/notification_conversion_helper_unittest.cc index 47a5fba9..526dfff 100644 --- a/chrome/browser/notifications/notification_conversion_helper_unittest.cc +++ b/chrome/browser/notifications/notification_conversion_helper_unittest.cc
@@ -62,7 +62,6 @@ base::UTF8ToUTF16("Title"), base::UTF8ToUTF16("This is a message."), icon, - blink::WebTextDirectionDefault, message_center::NotifierId(message_center::NotifierId::APPLICATION, "Notifier 1"), base::UTF8ToUTF16("Notifier's Name"),
diff --git a/chrome/browser/omnibox/omnibox_log.cc b/chrome/browser/omnibox/omnibox_log.cc index a1fa024..90d4b7e 100644 --- a/chrome/browser/omnibox/omnibox_log.cc +++ b/chrome/browser/omnibox/omnibox_log.cc
@@ -11,7 +11,6 @@ bool is_popup_open, size_t selected_index, bool is_paste_and_go, - bool last_action_was_paste, SessionID::id_type tab_id, metrics::OmniboxEventProto::PageClassification current_page_classification, base::TimeDelta elapsed_time_since_user_first_modified_omnibox, @@ -24,7 +23,6 @@ is_popup_open(is_popup_open), selected_index(selected_index), is_paste_and_go(is_paste_and_go), - last_action_was_paste(last_action_was_paste), tab_id(tab_id), current_page_classification(current_page_classification), elapsed_time_since_user_first_modified_omnibox(
diff --git a/chrome/browser/omnibox/omnibox_log.h b/chrome/browser/omnibox/omnibox_log.h index e908e4d0..08216bce 100644 --- a/chrome/browser/omnibox/omnibox_log.h +++ b/chrome/browser/omnibox/omnibox_log.h
@@ -26,7 +26,6 @@ bool is_popup_open, size_t selected_index, bool is_paste_and_go, - bool last_action_was_paste, SessionID::id_type tab_id, metrics::OmniboxEventProto::PageClassification current_page_classification, @@ -57,10 +56,6 @@ // (The codebase refers to both these types as paste-and-go.) bool is_paste_and_go; - // True if the user's last action was a paste or if (somehow) the user is - // still in the act of pasting. - bool last_action_was_paste; - // ID of the tab the selected autocomplete suggestion was opened in. // Set to -1 if we haven't yet determined the destination tab. SessionID::id_type tab_id;
diff --git a/chrome/browser/platform_util_linux.cc b/chrome/browser/platform_util_linux.cc index 4314762..c94f8fed 100644 --- a/chrome/browser/platform_util_linux.cc +++ b/chrome/browser/platform_util_linux.cc
@@ -39,7 +39,7 @@ base::Process process = base::LaunchProcess(argv, options); if (process.IsValid()) - base::EnsureProcessGetsReaped(process.pid()); + base::EnsureProcessGetsReaped(process.Pid()); } void XDGOpen(const std::string& path) {
diff --git a/chrome/browser/plugins/plugin_observer.cc b/chrome/browser/plugins/plugin_observer.cc index b4d472e1..dfd0577 100644 --- a/chrome/browser/plugins/plugin_observer.cc +++ b/chrome/browser/plugins/plugin_observer.cc
@@ -294,14 +294,15 @@ // process died, |plugin_pid| has been reused by a new process. The // consequence is that we will display |IDS_PLUGIN_DISCONNECTED_PROMPT| rather // than |IDS_PLUGIN_CRASHED_PROMPT| to the user, which seems acceptable. - base::ProcessHandle plugin_handle = base::kNullProcessHandle; - bool open_result = base::OpenProcessHandleWithAccess( - plugin_pid, PROCESS_QUERY_INFORMATION | SYNCHRONIZE, &plugin_handle); + base::Process plugin_process = + base::Process::OpenWithAccess(plugin_pid, + PROCESS_QUERY_INFORMATION | SYNCHRONIZE); bool is_running = false; - if (open_result) { - is_running = base::GetTerminationStatus(plugin_handle, NULL) == - base::TERMINATION_STATUS_STILL_RUNNING; - base::CloseProcessHandle(plugin_handle); + if (plugin_process.IsValid()) { + is_running = + base::GetTerminationStatus(plugin_process.Handle(), NULL) == + base::TERMINATION_STATUS_STILL_RUNNING; + plugin_process.Close(); } if (is_running) {
diff --git a/chrome/browser/printing/printer_manager_dialog_linux.cc b/chrome/browser/printing/printer_manager_dialog_linux.cc index 998ea5a..8513fa7a 100644 --- a/chrome/browser/printing/printer_manager_dialog_linux.cc +++ b/chrome/browser/printing/printer_manager_dialog_linux.cc
@@ -54,7 +54,7 @@ LOG(ERROR) << "Failed to open printer manager dialog "; return; } - base::EnsureProcessGetsReaped(process.pid()); + base::EnsureProcessGetsReaped(process.Pid()); } } // anonymous namespace
diff --git a/chrome/browser/printing/printing_layout_browsertest.cc b/chrome/browser/printing/printing_layout_browsertest.cc index 277c507..c38d6b1 100644 --- a/chrome/browser/printing/printing_layout_browsertest.cc +++ b/chrome/browser/printing/printing_layout_browsertest.cc
@@ -8,7 +8,7 @@ #include "base/files/file_util.h" #include "base/message_loop/message_loop.h" #include "base/path_service.h" -#include "base/process/process.h" +#include "base/process/process_handle.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "base/test/test_file_util.h" @@ -296,7 +296,7 @@ class DismissTheWindow : public base::DelegateSimpleThread::Delegate { public: DismissTheWindow() - : owner_process_(base::Process::Current().pid()) { + : owner_process_(base::GetCurrentProcId()) { } virtual void Run() {
diff --git a/chrome/browser/process_info_snapshot_mac_unittest.cc b/chrome/browser/process_info_snapshot_mac_unittest.cc index fe8c338b..51d212d5 100644 --- a/chrome/browser/process_info_snapshot_mac_unittest.cc +++ b/chrome/browser/process_info_snapshot_mac_unittest.cc
@@ -132,12 +132,12 @@ PCHECK(HANDLE_EINTR(read(fds[0], buf, 1)) == 1); std::vector<base::ProcessId> pid_list; - pid_list.push_back(process.pid()); + pid_list.push_back(process.Pid()); ProcessInfoSnapshot snapshot; ASSERT_TRUE(snapshot.Sample(pid_list)); ProcessInfoSnapshot::ProcInfoEntry proc_info; - ASSERT_TRUE(snapshot.GetProcInfo(process.pid(), &proc_info)); + ASSERT_TRUE(snapshot.GetProcInfo(process.Pid(), &proc_info)); // Effective user ID should be 0 (root). EXPECT_EQ(proc_info.euid, 0u); // Real user ID should match the calling process's user id.
diff --git a/chrome/browser/profiles/profile.cc b/chrome/browser/profiles/profile.cc index abd0779..7292b30c 100644 --- a/chrome/browser/profiles/profile.cc +++ b/chrome/browser/profiles/profile.cc
@@ -38,7 +38,8 @@ : restored_last_session_(false), sent_destroyed_notification_(false), accessibility_pause_level_(0), - is_guest_profile_(false) { + is_guest_profile_(false), + is_system_profile_(false) { } Profile::~Profile() { @@ -215,6 +216,10 @@ #endif } +bool Profile::IsSystemProfile() const { + return is_system_profile_; +} + bool Profile::IsNewProfile() { // The profile has been shut down if the prefs were loaded from disk, unless // first-run autoimport wrote them and reloaded the pref service.
diff --git a/chrome/browser/profiles/profile.h b/chrome/browser/profiles/profile.h index 45761ee..d7a60ce 100644 --- a/chrome/browser/profiles/profile.h +++ b/chrome/browser/profiles/profile.h
@@ -322,6 +322,9 @@ // Returns whether it is a guest session. virtual bool IsGuestSession() const; + // Returns whether it is a system profile. + virtual bool IsSystemProfile() const; + // Did the user restore the last session? This is set by SessionRestore. void set_restored_last_session(bool restored_last_session) { restored_last_session_ = restored_last_session; @@ -384,6 +387,10 @@ is_guest_profile_ = is_guest_profile; } + void set_is_system_profile(bool is_system_profile) { + is_system_profile_ = is_system_profile; + } + private: bool restored_last_session_; @@ -399,6 +406,9 @@ bool is_guest_profile_; + // A non-browsing profile not associated to a user. Sample use: User-Manager. + bool is_system_profile_; + DISALLOW_COPY_AND_ASSIGN(Profile); };
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc index 35d4763..a99e29a 100644 --- a/chrome/browser/profiles/profile_impl.cc +++ b/chrome/browser/profiles/profile_impl.cc
@@ -39,13 +39,10 @@ #include "chrome/browser/download/download_service.h" #include "chrome/browser/download/download_service_factory.h" #include "chrome/browser/history/top_sites.h" -#include "chrome/browser/net/chrome_net_log.h" #include "chrome/browser/net/net_pref_observer.h" #include "chrome/browser/net/predictor.h" #include "chrome/browser/net/pref_proxy_config_tracker.h" #include "chrome/browser/net/proxy_service_factory.h" -#include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings.h" -#include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings_factory.h" #include "chrome/browser/net/ssl_config_service_manager.h" #include "chrome/browser/plugins/chrome_plugin_service_filter.h" #include "chrome/browser/plugins/plugin_prefs.h" @@ -83,11 +80,6 @@ #include "chrome/grit/chromium_strings.h" #include "components/bookmarks/browser/bookmark_model.h" #include "components/content_settings/core/browser/host_content_settings_map.h" -#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.h" -#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_prefs.h" -#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h" -#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_statistics_prefs.h" -#include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h" #include "components/domain_reliability/monitor.h" #include "components/domain_reliability/service.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" @@ -431,6 +423,7 @@ #endif set_is_guest_profile(path == ProfileManager::GetGuestProfilePath()); + set_is_system_profile(path == ProfileManager::GetSystemProfilePath()); // Determine if prefetch is enabled for this profile. // If not profile_manager is present, it means we are in a unittest. @@ -642,69 +635,6 @@ session_cookie_mode = content::CookieStoreConfig::RESTORED_SESSION_COOKIES; } - ChromeNetLog* const net_log = g_browser_process->io_thread()->net_log(); - - base::Callback<void(bool)> data_reduction_proxy_unavailable; - scoped_ptr<data_reduction_proxy::DataReductionProxyParams> - data_reduction_proxy_params; - scoped_ptr<data_reduction_proxy::DataReductionProxyConfigurator> configurator; - scoped_ptr<data_reduction_proxy::DataReductionProxyStatisticsPrefs> - data_reduction_proxy_statistics_prefs; - scoped_ptr<data_reduction_proxy::DataReductionProxyEventStore> event_store; - DataReductionProxyChromeSettings* data_reduction_proxy_chrome_settings = - DataReductionProxyChromeSettingsFactory::GetForBrowserContext(this); - data_reduction_proxy_params = - data_reduction_proxy_chrome_settings->params()->Clone(); - data_reduction_proxy_unavailable = - base::Bind( - &data_reduction_proxy::DataReductionProxySettings::SetUnreachable, - base::Unretained(data_reduction_proxy_chrome_settings)); - // The event_store is used by DataReductionProxyChromeSettings, configurator, - // and ProfileIOData. Ownership is passed to the latter via - // ProfileIOData::Handle, which is only destroyed after - // BrowserContextKeyedServices, including DataReductionProxyChromeSettings - event_store.reset( - new data_reduction_proxy::DataReductionProxyEventStore( - BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI))); - // The configurator is used by DataReductionProxyChromeSettings and - // ProfileIOData. Ownership is passed to the latter via ProfileIOData::Handle, - // which is only destroyed after BrowserContextKeyedServices, - // including DataReductionProxyChromeSettings. - configurator.reset( - new data_reduction_proxy::DataReductionProxyConfigurator( - BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO), - net_log, - event_store.get())); - // Retain a raw pointer to use for initialization of data reduction proxy - // settings after ownership is passed - data_reduction_proxy::DataReductionProxyEventStore* - data_reduction_proxy_event_store = event_store.get(); - // Retain a raw pointer to use for initialization of data reduction proxy - // settings after ownership is passed. - data_reduction_proxy::DataReductionProxyConfigurator* - data_reduction_proxy_configurator = configurator.get(); -#if defined(OS_ANDROID) || defined(OS_IOS) - // On mobile we write data reduction proxy prefs directly to the pref service. - // On desktop we store data reduction proxy prefs in memory, writing to disk - // every 60 minutes and on termination. Shutdown hooks must be added for - // Android and iOS in order for non-zero delays to be supported. - // (http://crbug.com/408264) - base::TimeDelta commit_delay = base::TimeDelta(); -#else - base::TimeDelta commit_delay = base::TimeDelta::FromMinutes(60); -#endif - // TODO(bengr): Remove this in M-43. - data_reduction_proxy::MigrateStatisticsPrefs(g_browser_process->local_state(), - prefs_.get()); - data_reduction_proxy_statistics_prefs = - scoped_ptr<data_reduction_proxy::DataReductionProxyStatisticsPrefs>( - new data_reduction_proxy::DataReductionProxyStatisticsPrefs( - prefs_.get(), - base::MessageLoopProxy::current(), - commit_delay)); - data_reduction_proxy_chrome_settings->SetDataReductionProxyStatisticsPrefs( - data_reduction_proxy_statistics_prefs.get()); - // Make sure we initialize the ProfileIOData after everything else has been // initialized that we might be reading from the IO thread. @@ -712,19 +642,7 @@ cache_max_size, media_cache_path, media_cache_max_size, extensions_cookie_path, GetPath(), infinite_cache_path, predictor_, session_cookie_mode, GetSpecialStoragePolicy(), - CreateDomainReliabilityMonitor(local_state), - data_reduction_proxy_unavailable, - configurator.Pass(), - data_reduction_proxy_params.Pass(), - data_reduction_proxy_statistics_prefs.Pass(), - event_store.Pass()); - data_reduction_proxy_chrome_settings->InitDataReductionProxySettings( - data_reduction_proxy_configurator, - prefs_.get(), - g_browser_process->local_state(), - GetRequestContext(), - net_log, - data_reduction_proxy_event_store); + CreateDomainReliabilityMonitor(local_state)); #if defined(ENABLE_PLUGINS) ChromePluginServiceFilter::GetInstance()->RegisterResourceContext(
diff --git a/chrome/browser/profiles/profile_impl.h b/chrome/browser/profiles/profile_impl.h index fe601ec..286be73c 100644 --- a/chrome/browser/profiles/profile_impl.h +++ b/chrome/browser/profiles/profile_impl.h
@@ -41,12 +41,6 @@ class SequencedTaskRunner; } -namespace data_reduction_proxy { -class DataReductionProxyParams; -} - -class DataReductionProxyChromeSettings; - namespace domain_reliability { class DomainReliabilityMonitor; }
diff --git a/chrome/browser/profiles/profile_impl_io_data.cc b/chrome/browser/profiles/profile_impl_io_data.cc index b49d807..5af1186 100644 --- a/chrome/browser/profiles/profile_impl_io_data.cc +++ b/chrome/browser/profiles/profile_impl_io_data.cc
@@ -7,6 +7,7 @@ #include "base/bind.h" #include "base/command_line.h" #include "base/logging.h" +#include "base/memory/scoped_ptr.h" #include "base/metrics/field_trial.h" #include "base/prefs/pref_member.h" #include "base/prefs/pref_service.h" @@ -16,6 +17,7 @@ #include "base/strings/string_util.h" #include "base/threading/sequenced_worker_pool.h" #include "base/threading/worker_pool.h" +#include "chrome/browser/browser_process.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/custom_handlers/protocol_handler_registry.h" @@ -28,18 +30,19 @@ #include "chrome/browser/net/http_server_properties_manager_factory.h" #include "chrome/browser/net/predictor.h" #include "chrome/browser/net/quota_policy_channel_id_store.h" +#include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_io_data.h" #include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings.h" +#include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" #include "chrome/common/url_constants.h" -#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_auth_request_handler.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.h" -#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_interceptor.h" -#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.h" +#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h" +#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_prefs.h" +#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_statistics_prefs.h" -#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_usage_stats.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h" #include "components/domain_reliability/monitor.h" @@ -90,7 +93,6 @@ } // namespace using content::BrowserThread; -using data_reduction_proxy::DataReductionProxyParams; ProfileImplIOData::Handle::Handle(Profile* profile) : io_data_(new ProfileImplIOData), @@ -102,8 +104,6 @@ ProfileImplIOData::Handle::~Handle() { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - io_data_->data_reduction_proxy_statistics_prefs()->WritePrefs(); - if (io_data_->predictor_ != NULL) { // io_data_->predictor_ might be NULL if Init() was never called // (i.e. we shut down before ProfileImpl::DoFinalInit() got called). @@ -119,7 +119,7 @@ if (io_data_->http_server_properties_manager_) io_data_->http_server_properties_manager_->ShutdownOnPrefThread(); - io_data_->data_reduction_proxy_enabled_.Destroy(); + io_data_->data_reduction_proxy_io_data()->ShutdownOnUIThread(); io_data_->ShutdownOnUIThread(GetAllContextGetters().Pass()); } @@ -137,16 +137,7 @@ content::CookieStoreConfig::SessionCookieMode session_cookie_mode, storage::SpecialStoragePolicy* special_storage_policy, scoped_ptr<domain_reliability::DomainReliabilityMonitor> - domain_reliability_monitor, - const base::Callback<void(bool)>& data_reduction_proxy_unavailable, - scoped_ptr<data_reduction_proxy::DataReductionProxyConfigurator> - data_reduction_proxy_configurator, - scoped_ptr<data_reduction_proxy::DataReductionProxyParams> - data_reduction_proxy_params, - scoped_ptr<data_reduction_proxy::DataReductionProxyStatisticsPrefs> - data_reduction_proxy_statistics_prefs, - scoped_ptr<data_reduction_proxy::DataReductionProxyEventStore> - data_reduction_proxy_event_store) { + domain_reliability_monitor) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); DCHECK(!io_data_->lazy_params_); DCHECK(predictor); @@ -179,15 +170,20 @@ if (io_data_->domain_reliability_monitor_) io_data_->domain_reliability_monitor_->MoveToNetworkThread(); - io_data_->set_data_reduction_proxy_unavailable_callback( - data_reduction_proxy_unavailable); - io_data_->set_data_reduction_proxy_configurator( - data_reduction_proxy_configurator.Pass()); - io_data_->set_data_reduction_proxy_params(data_reduction_proxy_params.Pass()); - io_data_->set_data_reduction_proxy_statistics_prefs( - data_reduction_proxy_statistics_prefs.Pass()); - io_data_->set_data_reduction_proxy_event_store( - data_reduction_proxy_event_store.Pass()); + ChromeNetLog* const net_log = g_browser_process->io_thread()->net_log(); + + io_data_->set_data_reduction_proxy_io_data( + CreateDataReductionProxyChromeIOData( + net_log, profile_, profile_->GetPrefs(), + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO), + BrowserThread::GetMessageLoopProxyForThread( + BrowserThread::UI)).Pass()); + + DataReductionProxyChromeSettingsFactory::GetForBrowserContext(profile_)-> + InitDataReductionProxySettings(io_data_->data_reduction_proxy_io_data(), + profile_->GetPrefs(), + g_browser_process->local_state(), + profile_->GetRequestContext()); } content::ResourceContext* @@ -367,10 +363,6 @@ io_data_->safe_browsing_enabled()->MoveToThread( BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)); #endif - io_data_->data_reduction_proxy_enabled_.Init( - data_reduction_proxy::prefs::kDataReductionProxyEnabled, pref_service); - io_data_->data_reduction_proxy_enabled_.MoveToThread( - BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)); io_data_->InitializeOnUIThread(profile_); } @@ -458,52 +450,6 @@ FROM_HERE_WITH_EXPLICIT_FUNCTION( "436671 ProfileImplIOData::InitializeInternal2")); - set_data_reduction_proxy_auth_request_handler( - scoped_ptr<data_reduction_proxy::DataReductionProxyAuthRequestHandler> - (new data_reduction_proxy::DataReductionProxyAuthRequestHandler( - DataReductionProxyChromeSettings::GetClient(), - data_reduction_proxy_params(), - BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)))); - set_data_reduction_proxy_usage_stats( - scoped_ptr<data_reduction_proxy::DataReductionProxyUsageStats> - (new data_reduction_proxy::DataReductionProxyUsageStats( - data_reduction_proxy_params(), - BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI) - .get()))); - data_reduction_proxy_usage_stats()->set_unavailable_callback( - data_reduction_proxy_unavailable_callback()); - - // TODO(vadimt): Remove ScopedTracker below once crbug.com/436671 is fixed. - tracked_objects::ScopedTracker tracking_profile3( - FROM_HERE_WITH_EXPLICIT_FUNCTION( - "436671 ProfileImplIOData::InitializeInternal3")); - - scoped_ptr<data_reduction_proxy::DataReductionProxyNetworkDelegate> - data_reduction_proxy_network_delegate( - new data_reduction_proxy::DataReductionProxyNetworkDelegate( - chrome_network_delegate.Pass(), - data_reduction_proxy_params(), - data_reduction_proxy_auth_request_handler(), - base::Bind( - &data_reduction_proxy::DataReductionProxyConfigurator:: - GetProxyConfigOnIOThread, - base::Unretained(data_reduction_proxy_configurator())))); - data_reduction_proxy_network_delegate->InitProxyConfigOverrider( - base::Bind(data_reduction_proxy::OnResolveProxyHandler)); - data_reduction_proxy_network_delegate->InitStatisticsPrefsAndUMA( - BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI), - data_reduction_proxy_statistics_prefs(), - &data_reduction_proxy_enabled_, - data_reduction_proxy_usage_stats()); - network_delegate_ = data_reduction_proxy_network_delegate.Pass(); - - // Initialize context members. - - // TODO(vadimt): Remove ScopedTracker below once crbug.com/436671 is fixed. - tracked_objects::ScopedTracker tracking_profile4( - FROM_HERE_WITH_EXPLICIT_FUNCTION( - "436671 ProfileImplIOData::InitializeInternal4")); - ApplyProfileParamsToContext(main_context); if (http_server_properties_manager_) @@ -513,6 +459,9 @@ main_context->set_net_log(io_thread->net_log()); + network_delegate_ = data_reduction_proxy_io_data()->CreateNetworkDelegate( + chrome_network_delegate.Pass(), true).Pass(); + main_context->set_network_delegate(network_delegate_.get()); main_context->set_http_server_properties(http_server_properties()); @@ -640,10 +589,7 @@ // as possible. request_interceptors.insert( request_interceptors.begin(), - new data_reduction_proxy::DataReductionProxyInterceptor( - data_reduction_proxy_params(), - data_reduction_proxy_usage_stats(), - data_reduction_proxy_event_store())); + data_reduction_proxy_io_data()->CreateInterceptor().release()); main_job_factory_ = SetUpJobFactoryDefaults( main_job_factory.Pass(), request_interceptors.Pass(), @@ -797,10 +743,7 @@ // as possible. request_interceptors.insert( request_interceptors.begin(), - new data_reduction_proxy::DataReductionProxyInterceptor( - data_reduction_proxy_params(), - data_reduction_proxy_usage_stats(), - data_reduction_proxy_event_store())); + data_reduction_proxy_io_data()->CreateInterceptor().release()); scoped_ptr<net::URLRequestJobFactory> top_job_factory( SetUpJobFactoryDefaults(job_factory.Pass(), request_interceptors.Pass(), @@ -910,9 +853,3 @@ DCHECK(http_server_properties_manager_); http_server_properties_manager_->Clear(completion); } - -bool ProfileImplIOData::IsDataReductionProxyEnabled() const { - return data_reduction_proxy_enabled_.GetValue() || - base::CommandLine::ForCurrentProcess()->HasSwitch( - data_reduction_proxy::switches::kEnableDataReductionProxy); -}
diff --git a/chrome/browser/profiles/profile_impl_io_data.h b/chrome/browser/profiles/profile_impl_io_data.h index 8ea0f1a8..68b8260 100644 --- a/chrome/browser/profiles/profile_impl_io_data.h +++ b/chrome/browser/profiles/profile_impl_io_data.h
@@ -23,7 +23,6 @@ } // namespace content namespace data_reduction_proxy { -class DataReductionProxyConfigurator; class DataReductionProxyNetworkDelegate; } // namespace data_reduction_proxy @@ -68,16 +67,7 @@ content::CookieStoreConfig::SessionCookieMode session_cookie_mode, storage::SpecialStoragePolicy* special_storage_policy, scoped_ptr<domain_reliability::DomainReliabilityMonitor> - domain_reliability_monitor, - const base::Callback<void(bool)>& data_reduction_proxy_unavailable, - scoped_ptr<data_reduction_proxy::DataReductionProxyConfigurator> - data_reduction_proxy_configurator, - scoped_ptr<data_reduction_proxy::DataReductionProxyParams> - data_reduction_proxy_params, - scoped_ptr<data_reduction_proxy::DataReductionProxyStatisticsPrefs> - data_reduction_proxy_statistics_prefs, - scoped_ptr<data_reduction_proxy::DataReductionProxyEventStore> - data_reduction_proxy_event_store); + domain_reliability_monitor); // These Create*ContextGetter() functions are only exposed because the // circular relationship between Profile, ProfileIOData::Handle, and the @@ -157,8 +147,6 @@ DISALLOW_COPY_AND_ASSIGN(Handle); }; - bool IsDataReductionProxyEnabled() const override; - private: friend class base::RefCountedThreadSafe<ProfileImplIOData>; @@ -247,8 +235,6 @@ mutable scoped_ptr<net::SdchManager> sdch_manager_; mutable scoped_ptr<net::SdchOwner> sdch_policy_; - mutable BooleanPrefMember data_reduction_proxy_enabled_; - // Parameters needed for isolated apps. base::FilePath profile_path_; int app_cache_max_size_;
diff --git a/chrome/browser/profiles/profile_io_data.cc b/chrome/browser/profiles/profile_io_data.cc index 8c821a9..271fa2c4 100644 --- a/chrome/browser/profiles/profile_io_data.cc +++ b/chrome/browser/profiles/profile_io_data.cc
@@ -54,9 +54,7 @@ #include "chrome/common/url_constants.h" #include "components/content_settings/core/browser/content_settings_provider.h" #include "components/content_settings/core/browser/host_content_settings_map.h" -#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.h" -#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h" -#include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h" +#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h" #include "components/dom_distiller/core/url_constants.h" #include "components/startup_metric_utils/startup_metric_utils.h" #include "components/sync_driver/pref_names.h" @@ -109,9 +107,6 @@ #endif #if defined(OS_ANDROID) -#include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings.h" -#include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings_factory.h" -#include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h" #include "content/public/browser/android/content_protocol_handler.h" #endif // defined(OS_ANDROID) @@ -883,7 +878,13 @@ } bool ProfileIOData::IsDataReductionProxyEnabled() const { - return false; + return data_reduction_proxy_io_data()->IsEnabled(); +} + +void ProfileIOData::set_data_reduction_proxy_io_data( + scoped_ptr<data_reduction_proxy::DataReductionProxyIOData> + data_reduction_proxy_io_data) const { + data_reduction_proxy_io_data_ = data_reduction_proxy_io_data.Pass(); } base::WeakPtr<net::HttpServerProperties> @@ -1253,8 +1254,6 @@ quick_check_enabled_.Destroy(); if (media_device_id_salt_.get()) media_device_id_salt_->ShutdownOnUIThread(); - if (data_reduction_proxy_statistics_prefs_.get()) - data_reduction_proxy_statistics_prefs_->ShutdownOnUIThread(); session_startup_pref_.Destroy(); #if defined(ENABLE_CONFIGURATION_POLICY) if (url_blacklist_manager_) @@ -1309,6 +1308,8 @@ params.network_delegate = context->network_delegate(); params.http_server_properties = context->http_server_properties(); params.net_log = context->net_log(); + if (data_reduction_proxy_io_data_.get()) + params.proxy_delegate = data_reduction_proxy_io_data_->proxy_delegate(); network_controller_.reset(new DevToolsNetworkController());
diff --git a/chrome/browser/profiles/profile_io_data.h b/chrome/browser/profiles/profile_io_data.h index 966e86b..23ce4348 100644 --- a/chrome/browser/profiles/profile_io_data.h +++ b/chrome/browser/profiles/profile_io_data.h
@@ -22,11 +22,6 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/storage_partition_descriptor.h" #include "components/content_settings/core/common/content_settings_types.h" -#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_auth_request_handler.h" -#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.h" -#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_statistics_prefs.h" -#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_usage_stats.h" -#include "components/data_reduction_proxy/core/common/data_reduction_proxy_event_store.h" #include "content/public/browser/content_browser_client.h" #include "content/public/browser/resource_context.h" #include "net/cookies/cookie_monster.h" @@ -50,6 +45,10 @@ class ResourcePrefetchPredictorObserver; } +namespace data_reduction_proxy { +class DataReductionProxyIOData; +} + namespace extensions { class InfoMap; } @@ -250,15 +249,13 @@ // should only be called from there. bool GetMetricsEnabledStateOnIOThread() const; - // Returns whether or not data reduction proxy is enabled in the browser - // instance on which this profile resides. - virtual bool IsDataReductionProxyEnabled() const; - void set_client_cert_store_factory_for_testing( const base::Callback<scoped_ptr<net::ClientCertStore>()>& factory) { client_cert_store_factory_ = factory; } + bool IsDataReductionProxyEnabled() const; + protected: // A URLRequestContext for media that owns its HTTP factory, to ensure // it is deleted. @@ -367,84 +364,13 @@ void set_channel_id_service( net::ChannelIDService* channel_id_service) const; - data_reduction_proxy::DataReductionProxyParams* data_reduction_proxy_params() - const { - return data_reduction_proxy_params_.get(); - } + void set_data_reduction_proxy_io_data( + scoped_ptr<data_reduction_proxy::DataReductionProxyIOData> + data_reduction_proxy_io_data) const; - void set_data_reduction_proxy_params( - scoped_ptr<data_reduction_proxy::DataReductionProxyParams> - data_reduction_proxy_params) const { - data_reduction_proxy_params_ = data_reduction_proxy_params.Pass(); - } - - data_reduction_proxy::DataReductionProxyUsageStats* - data_reduction_proxy_usage_stats() const { - return data_reduction_proxy_usage_stats_.get(); - } - - void set_data_reduction_proxy_statistics_prefs( - scoped_ptr<data_reduction_proxy::DataReductionProxyStatisticsPrefs> - data_reduction_proxy_statistics_prefs) { - data_reduction_proxy_statistics_prefs_ = - data_reduction_proxy_statistics_prefs.Pass(); - } - - data_reduction_proxy::DataReductionProxyStatisticsPrefs* - data_reduction_proxy_statistics_prefs() const { - return data_reduction_proxy_statistics_prefs_.get(); - } - - void set_data_reduction_proxy_usage_stats( - scoped_ptr<data_reduction_proxy::DataReductionProxyUsageStats> - data_reduction_proxy_usage_stats) const { - data_reduction_proxy_usage_stats_ = - data_reduction_proxy_usage_stats.Pass(); - } - - base::Callback<void(bool)> data_reduction_proxy_unavailable_callback() const { - return data_reduction_proxy_unavailable_callback_; - } - - void set_data_reduction_proxy_unavailable_callback( - const base::Callback<void(bool)>& unavailable_callback) const { - data_reduction_proxy_unavailable_callback_ = unavailable_callback; - } - - data_reduction_proxy::DataReductionProxyConfigurator* - data_reduction_proxy_configurator() const { - return data_reduction_proxy_configurator_.get(); - } - - void set_data_reduction_proxy_configurator( - scoped_ptr<data_reduction_proxy::DataReductionProxyConfigurator> - data_reduction_proxy_configurator) const { - data_reduction_proxy_configurator_ = - data_reduction_proxy_configurator.Pass(); - } - - data_reduction_proxy::DataReductionProxyAuthRequestHandler* - data_reduction_proxy_auth_request_handler() const { - return data_reduction_proxy_auth_request_handler_.get(); - } - - void set_data_reduction_proxy_auth_request_handler( - scoped_ptr<data_reduction_proxy::DataReductionProxyAuthRequestHandler> - data_reduction_proxy_auth_request_handler) const { - data_reduction_proxy_auth_request_handler_ = - data_reduction_proxy_auth_request_handler.Pass(); - } - - data_reduction_proxy::DataReductionProxyEventStore* - data_reduction_proxy_event_store() const { - return data_reduction_proxy_event_store_.get(); - } - - void set_data_reduction_proxy_event_store( - scoped_ptr<data_reduction_proxy::DataReductionProxyEventStore> - data_reduction_proxy_event_store) const { - data_reduction_proxy_event_store_ = - data_reduction_proxy_event_store.Pass(); + data_reduction_proxy::DataReductionProxyIOData* + data_reduction_proxy_io_data() const { + return data_reduction_proxy_io_data_.get(); } net::FraudulentCertificateReporter* fraudulent_certificate_reporter() const { @@ -645,23 +571,8 @@ #endif mutable scoped_ptr<net::ChannelIDService> channel_id_service_; - // data_reduction_proxy_* classes must be declared before |network_delegate_|. - // The data_reduction_proxy_* classes are passed in to |network_delegate_|, - // so this ordering ensures that the |network_delegate_| never references - // freed objects. - mutable scoped_ptr<data_reduction_proxy::DataReductionProxyParams> - data_reduction_proxy_params_; - mutable scoped_ptr<data_reduction_proxy::DataReductionProxyUsageStats> - data_reduction_proxy_usage_stats_; - mutable scoped_ptr<data_reduction_proxy::DataReductionProxyStatisticsPrefs> - data_reduction_proxy_statistics_prefs_; - mutable base::Callback<void(bool)> data_reduction_proxy_unavailable_callback_; - mutable scoped_ptr<data_reduction_proxy::DataReductionProxyConfigurator> - data_reduction_proxy_configurator_; - mutable scoped_ptr<data_reduction_proxy::DataReductionProxyAuthRequestHandler> - data_reduction_proxy_auth_request_handler_; - mutable scoped_ptr<data_reduction_proxy::DataReductionProxyEventStore> - data_reduction_proxy_event_store_; + mutable scoped_ptr<data_reduction_proxy::DataReductionProxyIOData> + data_reduction_proxy_io_data_; mutable scoped_ptr<net::FraudulentCertificateReporter> fraudulent_certificate_reporter_;
diff --git a/chrome/browser/profiles/profile_manager.cc b/chrome/browser/profiles/profile_manager.cc index adff57b..5b7484f 100644 --- a/chrome/browser/profiles/profile_manager.cc +++ b/chrome/browser/profiles/profile_manager.cc
@@ -593,6 +593,16 @@ return guest_path.Append(chrome::kGuestProfileDir); } +// static +base::FilePath ProfileManager::GetSystemProfilePath() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + ProfileManager* profile_manager = g_browser_process->profile_manager(); + + base::FilePath system_path = profile_manager->user_data_dir(); + return system_path.Append(chrome::kSystemProfileDir); +} + base::FilePath ProfileManager::GenerateNextProfileDirectoryPath() { PrefService* local_state = g_browser_process->local_state(); DCHECK(local_state); @@ -1183,7 +1193,7 @@ } void ProfileManager::AddProfileToCache(Profile* profile) { - if (profile->IsGuestSession()) + if (profile->IsGuestSession() || profile->IsSystemProfile()) return; ProfileInfoCache& cache = GetProfileInfoCache(); if (profile->GetPath().DirName() != cache.GetUserDataDir())
diff --git a/chrome/browser/profiles/profile_manager.h b/chrome/browser/profiles/profile_manager.h index d246aadd..c16b6df8 100644 --- a/chrome/browser/profiles/profile_manager.h +++ b/chrome/browser/profiles/profile_manager.h
@@ -139,6 +139,9 @@ // Returns the full path to be used for guest profiles. static base::FilePath GetGuestProfilePath(); + // Returns the full path to be used for system profiles. + static base::FilePath GetSystemProfilePath(); + // Get the path of the next profile directory and increment the internal // count. // Lack of side effects:
diff --git a/chrome/browser/profiles/profile_manager_unittest.cc b/chrome/browser/profiles/profile_manager_unittest.cc index c05da3b..89238a2b 100644 --- a/chrome/browser/profiles/profile_manager_unittest.cc +++ b/chrome/browser/profiles/profile_manager_unittest.cc
@@ -384,6 +384,13 @@ EXPECT_EQ(expected_path, guest_path); } +TEST_F(ProfileManagerTest, GetSystemProfilePath) { + base::FilePath system_profile_path = ProfileManager::GetSystemProfilePath(); + base::FilePath expected_path = temp_dir_.path(); + expected_path = expected_path.Append(chrome::kSystemProfileDir); + EXPECT_EQ(expected_path, system_profile_path); +} + class UnittestGuestProfileManager : public UnittestProfileManager { public: explicit UnittestGuestProfileManager(const base::FilePath& user_data_dir)
diff --git a/chrome/browser/profiles/profile_window.cc b/chrome/browser/profiles/profile_window.cc index 320388f..c0891d5 100644 --- a/chrome/browser/profiles/profile_window.cc +++ b/chrome/browser/profiles/profile_window.cc
@@ -174,16 +174,16 @@ true); } -// Called after a |guest_profile| is available to be used by the user manager. +// Called after a |system_profile| is available to be used by the user manager. // Based on the value of |tutorial_mode| we determine a url to be displayed // by the webui and run the |callback|, if it exists. After opening a profile, // perform |profile_open_action|. -void OnUserManagerGuestProfileCreated( +void OnUserManagerSystemProfileCreated( const base::FilePath& profile_path_to_focus, profiles::UserManagerTutorialMode tutorial_mode, profiles::UserManagerProfileSelected profile_open_action, const base::Callback<void(Profile*, const std::string&)>& callback, - Profile* guest_profile, + Profile* system_profile, Profile::CreateStatus status) { if (status != Profile::CREATE_STATUS_INITIALIZED || callback.is_null()) return; @@ -214,7 +214,7 @@ profiles::USER_MANAGER_SELECT_PROFILE_CHROME_MEMORY) { page += profiles::kUserManagerSelectProfileChromeMemory; } - callback.Run(guest_profile, page); + callback.Run(system_profile, page); } // Updates Chrome services that require notification when @@ -396,16 +396,16 @@ return false; } -void CreateGuestProfileForUserManager( +void CreateSystemProfileForUserManager( const base::FilePath& profile_path_to_focus, profiles::UserManagerTutorialMode tutorial_mode, profiles::UserManagerProfileSelected profile_open_action, const base::Callback<void(Profile*, const std::string&)>& callback) { - // Create the guest profile, if necessary, and open the User Manager - // from the guest profile. + // Create the system profile, if necessary, and open the User Manager + // from the system profile. g_browser_process->profile_manager()->CreateProfileAsync( - ProfileManager::GetGuestProfilePath(), - base::Bind(&OnUserManagerGuestProfileCreated, + ProfileManager::GetSystemProfilePath(), + base::Bind(&OnUserManagerSystemProfileCreated, profile_path_to_focus, tutorial_mode, profile_open_action,
diff --git a/chrome/browser/profiles/profile_window.h b/chrome/browser/profiles/profile_window.h index ec7fdfd..b9df5c1d 100644 --- a/chrome/browser/profiles/profile_window.h +++ b/chrome/browser/profiles/profile_window.h
@@ -84,14 +84,14 @@ // Returns whether lock is available to this profile. bool IsLockAvailable(Profile* profile); -// Creates or reuses the guest profile needed by the user manager. Based on +// Creates or reuses the system profile needed by the user manager. Based on // the value of |tutorial_mode|, the user manager can show a specific // tutorial, or no tutorial at all. If a tutorial is not shown, then // |profile_path_to_focus| could be used to specify which user should be // focused. After a profile is opened from the user manager, perform // |profile_open_action|. |callback| is run with the custom url to be displayed, // as well as a pointer to the guest profile. -void CreateGuestProfileForUserManager( +void CreateSystemProfileForUserManager( const base::FilePath& profile_path_to_focus, profiles::UserManagerTutorialMode tutorial_mode, profiles::UserManagerProfileSelected profile_open_action,
diff --git a/chrome/browser/profiles/profiles_state.cc b/chrome/browser/profiles/profiles_state.cc index a673b01..3aa232a 100644 --- a/chrome/browser/profiles/profiles_state.cc +++ b/chrome/browser/profiles/profiles_state.cc
@@ -184,7 +184,7 @@ if (!cache.ProfileIsSigninRequiredAtIndex(index)) return NULL; - // The guest profile must have been loaded already. + // Profile loads synchronously if it was not previously created. Profile* guest_profile = profile_manager->GetProfile( ProfileManager::GetGuestProfilePath()); DCHECK(guest_profile);
diff --git a/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc b/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc index 27d0c77..5dd215a 100644 --- a/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc +++ b/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc
@@ -321,7 +321,7 @@ GURL page2("data:text/html,hello world2"); base::Process process2 = ShowSingletonTab(page2); ASSERT_TRUE(process2.IsValid()); - EXPECT_NE(process1.pid(), process2.pid()); + EXPECT_NE(process1.Pid(), process2.Pid()); EXPECT_TRUE(process1.IsProcessBackgrounded()); EXPECT_FALSE(process2.IsProcessBackgrounded()); @@ -330,15 +330,15 @@ GURL page3("data:text/html,hello world3"); base::Process process3 = OpenBackgroundTab(page3); ASSERT_TRUE(process3.IsValid()); - EXPECT_NE(process3.pid(), process1.pid()); - EXPECT_NE(process3.pid(), process2.pid()); + EXPECT_NE(process3.Pid(), process1.Pid()); + EXPECT_NE(process3.Pid(), process2.Pid()); EXPECT_TRUE(process1.IsProcessBackgrounded()); EXPECT_FALSE(process2.IsProcessBackgrounded()); EXPECT_TRUE(process3.IsProcessBackgrounded()); // Navigate back to the first page. Its renderer should be in foreground // again while the other renderers should be backgrounded. - EXPECT_EQ(process1.pid(), ShowSingletonTab(page1).pid()); + EXPECT_EQ(process1.Pid(), ShowSingletonTab(page1).Pid()); EXPECT_FALSE(process1.IsProcessBackgrounded()); EXPECT_TRUE(process2.IsProcessBackgrounded()); EXPECT_TRUE(process3.IsProcessBackgrounded());
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js index 3ebbef2..2776b6f 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js
@@ -208,6 +208,28 @@ if (this.currentRange_) this.currentRange_.getStart().getNode().doDefault(); break; + case 'continuousRead': + global.isReadingContinuously = true; + var continueReading = function(prevRange) { + if (!global.isReadingContinuously) + return; + + new Output().withSpeechAndBraille( + this.currentRange_, prevRange, Output.EventType.NAVIGATE) + .onSpeechEnd(function() { continueReading(prevRange); }) + .onSpeechInterrupted( + function() { global.isReadingContinuously = false; }) + .go(); + prevRange = this.currentRange_; + this.currentRange_ = + this.currentRange_.move(cursors.Unit.NODE, Dir.FORWARD); + + if (this.currentRange_.equals(prevRange)) + global.isReadingContinuously = false; + }.bind(this); + + continueReading(null); + return; } if (pred) { @@ -224,7 +246,9 @@ var prevRange = this.currentRange_; this.currentRange_ = current; - new Output(this.currentRange_, prevRange, Output.EventType.NAVIGATE); + new Output().withSpeechAndBraille( + this.currentRange_, prevRange, Output.EventType.NAVIGATE) + .go(); } }, @@ -245,7 +269,9 @@ if (node.root.role != chrome.automation.RoleType.desktop && !this.active_) return; - new Output(this.currentRange_, prevRange, evt.type); + new Output().withSpeechAndBraille( + this.currentRange_, prevRange, evt.type) + .go(); }, /** @@ -265,7 +291,9 @@ this.currentRange_ = cursors.Range.fromNode(node); if (this.currentRange_) - new Output(this.currentRange_, null, evt.type); + new Output().withSpeechAndBraille( + this.currentRange_, null, evt.type) + .go(); }, /** @@ -303,7 +331,9 @@ } this.editableTextHandler.changed(textChangeEvent); - new Output(this.currentRange_, null, evt.type, {braille: true}); + new Output().withBraille( + this.currentRange_, null, evt.type) + .go(); }, /**
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/background_test.extjs b/chrome/browser/resources/chromeos/chromevox/cvox2/background/background_test.extjs index 0a5566ee..7ed70f7c 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/background_test.extjs +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/background_test.extjs
@@ -166,7 +166,8 @@ }.bind(this)); }); -TEST_F('BackgroundTest', 'SelectSingleBasic', function() { +// Flaky: http://crbug.com/451362 +TEST_F('BackgroundTest', 'DISABLED_SelectSingleBasic', function() { this.runWithDocument(this.formsDoc, function(tabId) { var sendDownToSelect = this.sendKeyToElement.bind(this, tabId, 'Down', '#fruitSelect'); @@ -177,3 +178,23 @@ cvox.ChromeVox.tts.finishExpectations(); }.bind(this)); }); + +TEST_F('BackgroundTest', 'ContinuousRead', function() { + cvox.ChromeVox.tts.expectSpeech('start', null, true); + this.runWithDocument(this.linksAndHeadingsDoc, function() { + var doCmd = this.doCmd.bind(this); + var expect = + cvox.ChromeVox.tts.expectSpeechAfter.bind(cvox.ChromeVox.tts); + var sendEndEvent = function() { + window.setTimeout(function() { + this.sendEndEvent(); + }.bind(this), 0); + }.bind(cvox.ChromeVox.tts); + + expect('start', doCmd('continuousRead')); + expect('alpha Link', sendEndEvent); + expect('beta Link', sendEndEvent); + expect('Heading charlie', sendEndEvent); + cvox.ChromeVox.tts.finishExpectations(); + }.bind(this)); +});
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js index eb359827..f093bac 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js
@@ -40,15 +40,9 @@ * = suffix: used to specify substitution only if not previously appended. * For example, $name= would insert the name attribute only if no name * attribute had been inserted previously. - * @param {!cursors.Range} range - * @param {cursors.Range} prevRange - * @param {chrome.automation.EventType|Output.EventType} type - * @param {{braille: (boolean|undefined), speech: (boolean|undefined)}=} - * opt_options * @constructor */ -Output = function(range, prevRange, type, opt_options) { - opt_options = opt_options || {braille: true, speech: true}; +Output = function() { // TODO(dtseng): Include braille specific rules. /** @type {!cvox.Spannable} */ this.buffer_ = new cvox.Spannable(); @@ -56,19 +50,18 @@ this.brailleBuffer_ = new cvox.Spannable(); /** @type {!Array.<Object>} */ this.locations_ = []; + /** @type {function()} */ + this.speechStartCallback_ = function() {}; + /** @type {function()} */ + this.speechEndCallback_ = function() {}; + /** @type {function()} */ + this.speechInterruptedCallback_ = function() {}; /** * Current global options. * @type {{speech: boolean, braille: boolean, location: boolean}} */ this.formatOptions_ = {speech: true, braille: false, location: true}; - - this.render_(range, prevRange, type); - if (opt_options.speech) - this.handleSpeech(); - if (opt_options.braille) - this.handleBraille(); - this.handleDisplay(); }; /** @@ -240,26 +233,99 @@ }, /** - * Handle output to speech. + * Specify ranges for speech. + * @param {!cursors.Range} range + * @param {cursors.Range} prevRange + * @param {chrome.automation.EventType|Output.EventType} type + * @return {!Output} */ - handleSpeech: function() { - var buff = this.buffer_; - if (!buff.toString()) - return; + withSpeech: function(range, prevRange, type) { + this.formatOptions_ = {speech: true, braille: false, location: true}; + this.render_(range, prevRange, type, this.buffer_); + return this; + }, - cvox.ChromeVox.tts.speak(buff.toString(), cvox.QueueMode.FLUSH); + /** + * Specify ranges for braille. + * @param {!cursors.Range} range + * @param {cursors.Range} prevRange + * @param {chrome.automation.EventType|Output.EventType} type + * @return {!Output} + */ + withBraille: function(range, prevRange, type) { + this.formatOptions_ = {speech: false, braille: true, location: false}; + this.render_(range, prevRange, type, this.brailleBuffer_); + return this; + }, + + /** + * Specify the same ranges for speech and braille. + * @param {!cursors.Range} range + * @param {cursors.Range} prevRange + * @param {chrome.automation.EventType|Output.EventType} type + * @return {!Output} + */ + withSpeechAndBraille: function(range, prevRange, type) { + this.withSpeech(range, prevRange, type); + this.withBraille(range, prevRange, type); + return this; + }, + + /** + * Triggers callback for a speech event. + * @param {function()} callback + */ + onSpeechStart: function(callback) { + this.speechStartCallback_ = callback; + return this; + }, + + /** + * Triggers callback for a speech event. + * @param {function()} callback + */ + onSpeechEnd: function(callback) { + this.speechEndCallback_ = callback; + return this; + }, + + /** + * Triggers callback for a speech event. + * @param {function()} callback + */ + onSpeechInterrupted: function(callback) { + this.speechInterruptedCallback_ = callback; + return this; + }, + + /** + * Executes all specified output. + */ + go: function() { + // Speech. + var buff = this.buffer_; + + var onEvent = function(evt) { + switch (evt.type) { + case 'start': this.speechStartCallback_(); break; + case 'end': this.speechEndCallback_(); break; + case 'interrupted': this.speechInterruptedCallback_(); break; + } + }.bind(this); + + if (buff.toString()) { + cvox.ChromeVox.tts.speak( + buff.toString(), cvox.QueueMode.FLUSH, {onEvent: onEvent}); + } + var actions = buff.getSpansInstanceOf(Output.Action); if (actions) { actions.forEach(function(a) { a.run(); }); } - }, - /** - * Handles output to braille. - */ - handleBraille: function() { + // Braille. var selSpan = this.brailleBuffer_.getSpanInstanceOf(Output.SelectionSpan); var startIndex = -1, endIndex = -1; @@ -285,13 +351,10 @@ endIndex: endIndex }); - cvox.ChromeVox.braille.write(output); - }, + if (this.brailleBuffer_) + cvox.ChromeVox.braille.write(output); - /** - * Handles output to visual display. - */ - handleDisplay: function() { + // Display. chrome.accessibilityPrivate.setFocusRing(this.locations_); }, @@ -301,25 +364,14 @@ * @param {!cursors.Range} range * @param {cursors.Range} prevRange * @param {chrome.automation.EventType|string} type + * @param {!cvox.Spannable} buff Buffer to receive rendered output. * @private */ - render_: function(range, prevRange, type) { - var buff = new cvox.Spannable(); - var brailleBuff = new cvox.Spannable(); + render_: function(range, prevRange, type, buff) { if (range.isSubNode()) this.subNode_(range, prevRange, type, buff); else this.range_(range, prevRange, type, buff); - - this.formatOptions_.braille = true; - this.formatOptions_.location = false; - if (range.isSubNode()) - this.subNode_(range, prevRange, type, brailleBuff); - else - this.range_(range, prevRange, type, brailleBuff); - - this.buffer_ = buff; - this.brailleBuffer_ = brailleBuff; }, /**
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/output_test.extjs b/chrome/browser/resources/chromeos/chromevox/cvox2/background/output_test.extjs index 2425451..8e2709f 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/output_test.extjs +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/output_test.extjs
@@ -26,7 +26,7 @@ function(root) { var link = root.firstChild.firstChild; var range = cursors.Range.fromNode(link); - var o = new Output(range, null, 'navigate'); + var o = new Output().withSpeechAndBraille(range, null, 'navigate'); assertEqualsJSON({string_: 'Click here Link', 'spans_': [ {value: 'name', start: 0, end: 10}, // Link earcon. @@ -36,4 +36,3 @@ testDone(); }.bind(this)); }); -
diff --git a/chrome/browser/resources/chromeos/chromevox/host/chrome/tts_background.js b/chrome/browser/resources/chromeos/chromevox/host/chrome/tts_background.js index 9886e2f..91b9e5e 100644 --- a/chrome/browser/resources/chromeos/chromevox/host/chrome/tts_background.js +++ b/chrome/browser/resources/chromeos/chromevox/host/chrome/tts_background.js
@@ -229,6 +229,7 @@ if (splitTextString.length > 2) { var startCallback = properties['startCallback']; var endCallback = properties['endCallback']; + var onEvent = properties['onEvent']; for (var i = 0; i < splitTextString.length; i++) { var propertiesCopy = {}; for (var p in properties) { @@ -237,6 +238,8 @@ propertiesCopy['startCallback'] = i == 0 ? startCallback : null; propertiesCopy['endCallback'] = i == (splitTextString.length - 1) ? endCallback : null; + propertiesCopy['onEvent'] = + i == (splitTextString.length - 1) ? onEvent : null; this.speak(splitTextString[i], queueMode, propertiesCopy); queueMode = cvox.QueueMode.QUEUE; } @@ -345,9 +348,12 @@ this.currentUtterance_ = this.utteranceQueue_.shift(); var utteranceId = this.currentUtterance_.id; - this.currentUtterance_.properties['onEvent'] = goog.bind(function(event) { - this.onTtsEvent_(event, utteranceId); - }, this); + this.currentUtterance_.properties['onEvent'] = + this.currentUtterance_.properties['onEvent'] || + goog.bind(function(event) { + this.onTtsEvent_(event, utteranceId); + }, + this); var validatedProperties = {}; for (var i = 0; i < cvox.TtsBackground.ALLOWED_PROPERTIES_.length; i++) {
diff --git a/chrome/browser/resources/chromeos/chromevox/manifest.json.jinja2 b/chrome/browser/resources/chromeos/chromevox/manifest.json.jinja2 index b471ec7..c7e43e4b 100644 --- a/chrome/browser/resources/chromeos/chromevox/manifest.json.jinja2 +++ b/chrome/browser/resources/chromeos/chromevox/manifest.json.jinja2
@@ -156,6 +156,12 @@ "suggested_key": { "chromeos": "Search+Ctrl+Q" } + }, + "continuousRead": { + "description": "__MSG_CHROMEVOX_READ_FROM_HERE__", + "suggested_key": { + "chromeos": "Search+R" + } } }, {% endif %}
diff --git a/chrome/browser/resources/chromeos/chromevox/testing/mock_tts.js b/chrome/browser/resources/chromeos/chromevox/testing/mock_tts.js index b41c0ad3..0915e112 100644 --- a/chrome/browser/resources/chromeos/chromevox/testing/mock_tts.js +++ b/chrome/browser/resources/chromeos/chromevox/testing/mock_tts.js
@@ -8,6 +8,11 @@ * @extends {cvox.TtsInterface} */ var MockTts = function() { + /** + * The event handler for the most recent call to |speak|. + * @private + */ + this.onEvent_; }; MockTts.prototype = { @@ -29,6 +34,9 @@ /** @override */ speak: function(textString, queueMode, properties) { + if (properties) + this.onEvent_ = properties['onEvent']; + this.process_(textString); }, @@ -69,6 +77,22 @@ }, /** + * Fakes an event to |onEvent|. + */ + sendStartEvent: function() { + if (this.onEvent_) + this.onEvent_({type: 'start'}); + }, + + /** + * Fakes an event to |onEvent|. + */ + sendEndEvent: function() { + if (this.onEvent_) + this.onEvent_({type: 'end'}); + }, + + /** * @private * @param {string} expectedText Text expected spoken. * @param {{startCallback: function() : void,
diff --git a/chrome/browser/resources/chromeos/login/header_bar.css b/chrome/browser/resources/chromeos/login/header_bar.css index 05bdefa..7676f02 100644 --- a/chrome/browser/resources/chromeos/login/header_bar.css +++ b/chrome/browser/resources/chromeos/login/header_bar.css
@@ -4,6 +4,7 @@ */ #login-header-bar { + -webkit-padding-start: 15px; border-bottom: 3px solid black; bottom: 0; left: 0; @@ -36,10 +37,6 @@ -webkit-transition: opacity 2s ease-out; } -.header-bar-item:first-child { - -webkit-padding-start: 15px; -} - #login-header-bar button, #login-header-bar button:active, #login-header-bar button:focus, @@ -73,6 +70,7 @@ } #login-header-bar #shutdown-button, +#login-header-bar #restart-button, #login-header-bar #add-user-button, #login-header-bar #guest-user-button, #login-header-bar #cancel-multiple-sign-in-button { @@ -83,6 +81,7 @@ } html[dir=rtl] #login-header-bar #shutdown-button, +html[dir=rtl] #login-header-bar #restart-button, html[dir=rtl] #login-header-bar #add-user-button, html[dir=rtl] #login-header-bar #guest-user-button, html[dir=rtl] #login-header-bar #cancel-multiple-sign-in-button { @@ -93,6 +92,10 @@ background-image: url(chrome://theme/IDR_ICON_POWER_WHITE); } +#login-header-bar #restart-button { + background-image: url(chrome://theme/IDR_ICON_POWER_WHITE); +} + #login-header-bar #add-user-button { background-image: url(chrome://theme/IDR_ICON_ADD_USER_WHITE); }
diff --git a/chrome/browser/resources/chromeos/login/header_bar.html b/chrome/browser/resources/chromeos/login/header_bar.html index 9f5f9728..b523745 100644 --- a/chrome/browser/resources/chromeos/login/header_bar.html +++ b/chrome/browser/resources/chromeos/login/header_bar.html
@@ -3,6 +3,10 @@ <button id="shutdown-button" class="custom-appearance" i18n-content="shutDown"></button> </div> + <div id="restart-header-bar-item" class="header-bar-item"> + <button id="restart-button" class="custom-appearance" + i18n-content="restart"></button> + </div> <div id="apps-header-bar-item" class="header-bar-item" hidden> <button id="show-apps-button" class="custom-appearance" i18n-content="showApps"></button>
diff --git a/chrome/browser/resources/chromeos/login/header_bar.js b/chrome/browser/resources/chromeos/login/header_bar.js index 18735c3..3a3ba9ba 100644 --- a/chrome/browser/resources/chromeos/login/header_bar.js +++ b/chrome/browser/resources/chromeos/login/header_bar.js
@@ -21,6 +21,14 @@ // Whether guest button should be shown when header bar is in normal mode. showGuest_: false, + // Whether the reboot button should be shown the when header bar is in + // normal mode. + showReboot_: false, + + // Whether the shutdown button should be shown when the header bar is in + // normal mode. + showShutdown_: true, + // Current UI state of the sign-in screen. signinUIState_: SIGNIN_UI_STATE.HIDDEN, @@ -33,6 +41,10 @@ this.handleShutdownClick_); $('shutdown-button').addEventListener('click', this.handleShutdownClick_); + $('restart-header-bar-item').addEventListener('click', + this.handleShutdownClick_); + $('restart-button').addEventListener('click', + this.handleShutdownClick_); $('add-user-button').addEventListener('click', this.handleAddUserClick_); $('cancel-add-user-button').addEventListener('click', @@ -177,6 +189,26 @@ }, /** + * If true the "Restart" button is shown. + * + * @type {boolean} + */ + set showRebootButton(value) { + this.showReboot_ = value; + this.updateUI_(); + }, + + /** + * If true the "Shutdown" button is shown. + * + * @type {boolean} + */ + set showShutdownButton(value) { + this.showShutdown_ = value; + this.updateUI_(); + }, + + /** * Current header bar UI / sign in state. * * @type {number} state Current state of the sign-in screen (see @@ -245,6 +277,8 @@ wrongHWIDWarningIsActive || isSamlPasswordConfirm || isMultiProfilesUI; + $('restart-header-bar-item').hidden = !this.showReboot_; + $('shutdown-header-bar-item').hidden = !this.showShutdown_; $('sign-out-user-item').hidden = !isLockScreen; $('add-user-header-bar-item').hidden =
diff --git a/chrome/browser/resources/chromeos/login/login_common.js b/chrome/browser/resources/chromeos/login/login_common.js index 0d5895d..2c07869 100644 --- a/chrome/browser/resources/chromeos/login/login_common.js +++ b/chrome/browser/resources/chromeos/login/login_common.js
@@ -113,6 +113,16 @@ }; /** + * When |showShutdown| is set to "true", the shutdown button is shown and the + * reboot button hidden. If set to "false", the reboot button is visible and + * the shutdown button hidden. + */ + Oobe.showShutdown = function(showShutdown) { + $('login-header-bar').showShutdownButton = showShutdown; + $('login-header-bar').showRebootButton = !showShutdown; + }; + + /** * Enables keyboard driven flow. */ Oobe.enableKeyboardFlow = function(value) {
diff --git a/chrome/browser/resources/component_extension_resources.grd b/chrome/browser/resources/component_extension_resources.grd index 7c80fcf3..0010138 100644 --- a/chrome/browser/resources/component_extension_resources.grd +++ b/chrome/browser/resources/component_extension_resources.grd
@@ -167,6 +167,7 @@ <include name="IDR_PDF_PDF_JS" file="pdf/pdf.js" type="BINDATA" /> <include name="IDR_PDF_VIEWPORT_JS" file="pdf/viewport.js" type="BINDATA" /> <include name="IDR_PDF_OPEN_PDF_PARAMS_PARSER_JS" file="pdf/open_pdf_params_parser.js" type="BINDATA" /> + <include name="IDR_PDF_NAVIGATOR_JS" file="pdf/navigator.js" type="BINDATA" /> <include name="IDR_PDF_PDF_SCRIPTING_API_JS" file="pdf/pdf_scripting_api.js" type="BINDATA" /> <include name="IDR_PDF_CONTENT_SCRIPT_JS" file="pdf/content_script.js" type="BINDATA" />
diff --git a/chrome/browser/resources/cryptotoken/cryptotokenapprovedorigins.js b/chrome/browser/resources/cryptotoken/cryptotokenapprovedorigins.js index a28a934..89fc759 100644 --- a/chrome/browser/resources/cryptotoken/cryptotokenapprovedorigins.js +++ b/chrome/browser/resources/cryptotoken/cryptotokenapprovedorigins.js
@@ -30,36 +30,28 @@ CryptoTokenApprovedOrigin.prototype.isApprovedOrigin = function(origin, opt_tabId) { return new Promise(function(resolve, reject) { - if (!chrome.tabs || !chrome.tabs.get) { - reject(); - return; - } - if (!chrome.windows || !chrome.windows.get) { - reject(); - return; - } - if (!opt_tabId) { + if (opt_tabId === undefined) { resolve(false); return; } var tabId = /** @type {number} */ (opt_tabId); - chrome.tabs.get(tabId, function(tab) { - if (chrome.runtime.lastError) { - resolve(false); - return; - } - if (!tab.active) { - resolve(false); - return; - } - chrome.windows.get(tab.windowId, function(aWindow) { - if (!aWindow || !aWindow.focused) { - resolve(false); - return; - } - var tabOrigin = getOriginFromUrl(tab.url); - resolve(tabOrigin == origin); - }); - }); + tabInForeground(tabId).then(function(result) { + if (!result) { + resolve(false); + return; + } + if (!chrome.tabs || !chrome.tabs.get) { + reject(); + return; + } + chrome.tabs.get(tabId, function(tab) { + if (chrome.runtime.lastError) { + resolve(false); + return; + } + var tabOrigin = getOriginFromUrl(tab.url); + resolve(tabOrigin == origin); + }); + }); }); };
diff --git a/chrome/browser/resources/cryptotoken/cryptotokenbackground.js b/chrome/browser/resources/cryptotoken/cryptotokenbackground.js index 800cdf8..e7ebcc71 100644 --- a/chrome/browser/resources/cryptotoken/cryptotokenbackground.js +++ b/chrome/browser/resources/cryptotoken/cryptotokenbackground.js
@@ -37,6 +37,81 @@ new GoogleCorpIndividualAttestation()); /** + * @param {*} request The received request + * @return {boolean} Whether the request is a register/enroll request. + */ +function isRegisterRequest(request) { + if (!request) { + return false; + } + switch (request.type) { + case GnubbyMsgTypes.ENROLL_WEB_REQUEST: + return true; + + case MessageTypes.U2F_REGISTER_REQUEST: + return true; + + default: + return false; + } +} + +/** + * Default response callback to deliver a response to a request. + * @param {*} request The received request. + * @param {function(*): void} sendResponse A callback that delivers a response. + * @param {*} response The response to return. + */ +function defaultResponseCallback(request, sendResponse, response) { + response['requestId'] = request['requestId']; + try { + sendResponse(response); + } catch (e) { + console.warn(UTIL_fmt('caught: ' + e.message)); + } +} + +/** + * Response callback that delivers a response to a request only when the + * sender is a foreground tab. + * @param {*} request The received request. + * @param {!MessageSender} sender The message sender. + * @param {function(*): void} sendResponse A callback that delivers a response. + * @param {*} response The response to return. + */ +function sendResponseToActiveTabOnly(request, sender, sendResponse, response) { + tabInForeground(sender.tab.id).then(function(result) { + // If the tab is no longer in the foreground, drop the result: the user + // is no longer interacting with the tab that originated the request. + if (result) { + defaultResponseCallback(request, sendResponse, response); + } + }); +} + +/** + * Common handler for messages received from chrome.runtime.sendMessage and + * chrome.runtime.connect + postMessage. + * @param {*} request The received request + * @param {!MessageSender} sender The message sender + * @param {function(*): void} sendResponse A callback that delivers a response + * @return {Closeable} A Closeable request handler. + */ +function messageHandler(request, sender, sendResponse) { + var responseCallback; + if (isRegisterRequest(request)) { + responseCallback = + sendResponseToActiveTabOnly.bind(null, request, sender, sendResponse); + } else { + responseCallback = + defaultResponseCallback.bind(null, request, sendResponse); + } + var closeable = handleWebPageRequest(/** @type {Object} */(request), + sender, responseCallback); + return closeable; +} + +/** * Listen to individual messages sent from (whitelisted) webpages via * chrome.runtime.sendMessage * @param {*} request The received request @@ -48,28 +123,22 @@ if (sender.id && sender.id === LOG_SAVER_EXTENSION_ID) { return handleLogSaverMessage(request); } - var closeable = handleWebPageRequest(/** @type {Object} */(request), - sender, function(response) { - response['requestId'] = request['requestId']; - try { - sendResponse(response); - } catch (e) { - console.warn(UTIL_fmt('caught: ' + e.message)); - } - }); + + messageHandler(request, sender, sendResponse); return true; // Tell Chrome not to destroy sendResponse yet } chrome.runtime.onMessageExternal.addListener(messageHandlerExternal); // Listen to direct connection events, and wire up a message handler on the port chrome.runtime.onConnectExternal.addListener(function(port) { + function sendResponse(response) { + port.postMessage(response); + } + var closeable; port.onMessage.addListener(function(request) { - closeable = handleWebPageRequest(request, port.sender, - function(response) { - response['requestId'] = request['requestId']; - port.postMessage(response); - }); + var sender = /** @type {!MessageSender} */ (port.sender); + closeable = messageHandler(request, sender, sendResponse); }); port.onDisconnect.addListener(function() { if (closeable) {
diff --git a/chrome/browser/resources/cryptotoken/webrequestsender.js b/chrome/browser/resources/cryptotoken/webrequestsender.js index d3fdf3d2..7907120 100644 --- a/chrome/browser/resources/cryptotoken/webrequestsender.js +++ b/chrome/browser/resources/cryptotoken/webrequestsender.js
@@ -131,3 +131,35 @@ }); } } + +/** + * Checks whether the given tab is in the foreground, i.e. is the active tab + * of the focused window. + * @param {number} tabId The tab id to check. + * @return {Promise.<boolean>} A promise for the result of the check. + */ +function tabInForeground(tabId) { + return new Promise(function(resolve, reject) { + if (!chrome.tabs || !chrome.tabs.get) { + reject(); + return; + } + if (!chrome.windows || !chrome.windows.get) { + reject(); + return; + } + chrome.tabs.get(tabId, function(tab) { + if (chrome.runtime.lastError) { + resolve(false); + return; + } + if (!tab.active) { + resolve(false); + return; + } + chrome.windows.get(tab.windowId, function(aWindow) { + resolve(aWindow && aWindow.focused); + }); + }); + }); +}
diff --git a/chrome/browser/resources/hotword/constants.js b/chrome/browser/resources/hotword/constants.js index 32692a88..ce5dc98e3 100644 --- a/chrome/browser/resources/hotword/constants.js +++ b/chrome/browser/resources/hotword/constants.js
@@ -36,6 +36,20 @@ var COMMAND_FIELD_NAME = 'cmd'; /** + * The speaker model file name. + * @const {string} + */ +var SPEAKER_MODEL_FILE_NAME = 'speaker_model.data'; + +/** + * The size of the file system requested for reading the speaker model file. + * As of January 27th, 2015, the speaker model is 290 bytes. This number + * should always be larger than the speaker model file size. + * @const {number} + */ +var FILE_SYSTEM_SIZE_BYTES = 526; + +/** * Time to wait for expected messages, in milliseconds. * @enum {number} */ @@ -234,8 +248,10 @@ AUDIO_LOG_SECONDS: AUDIO_LOG_SECONDS, CLIENT_PORT_NAME: CLIENT_PORT_NAME, COMMAND_FIELD_NAME: COMMAND_FIELD_NAME, + FILE_SYSTEM_SIZE_BYTES: FILE_SYSTEM_SIZE_BYTES, SHARED_MODULE_ID: SHARED_MODULE_ID, SHARED_MODULE_ROOT: SHARED_MODULE_ROOT, + SPEAKER_MODEL_FILE_NAME: SPEAKER_MODEL_FILE_NAME, UI_LANGUAGE: UI_LANGUAGE, CommandToPage: CommandToPage, CommandFromPage: CommandFromPage,
diff --git a/chrome/browser/resources/hotword/manager.js b/chrome/browser/resources/hotword/manager.js index 83b6f105..3f092dc6 100644 --- a/chrome/browser/resources/hotword/manager.js +++ b/chrome/browser/resources/hotword/manager.js
@@ -34,6 +34,11 @@ stateManager.updateStatus(); }); + // Detect a request to delete the speaker model. + chrome.hotwordPrivate.onDeleteSpeakerModel.addListener(function() { + hotword.TrainingManager.handleDeleteSpeakerModel(); + }); + // Detect when the shared module containing the NaCL module and language model // is installed. chrome.management.onInstalled.addListener(function(info) {
diff --git a/chrome/browser/resources/hotword/manifest.json b/chrome/browser/resources/hotword/manifest.json index ef061c7f..155c241 100644 --- a/chrome/browser/resources/hotword/manifest.json +++ b/chrome/browser/resources/hotword/manifest.json
@@ -3,7 +3,7 @@ "key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDbHXRPiq2De9EJ+4pvNN6uE/D2avxrqyLSpA/Hq3II+btkPl1gboY3oUPTfevpVOFa90Y1c1b3/W682dXqybT0klIvFLKhdQx0LiVqSUQyIaDrwOCSo/ZcukbEwDRojegWymCjHvX6WZk4kKZzTJYzY1vrp0TWKLhttEMN9KFmowIDAQAB", "name": "Hotword triggering", - "version": "0.0.1.3", + "version": "0.0.1.4", "manifest_version": 2, "background": {
diff --git a/chrome/browser/resources/hotword/training_manager.js b/chrome/browser/resources/hotword/training_manager.js index fa51dcb..1bddc5f 100644 --- a/chrome/browser/resources/hotword/training_manager.js +++ b/chrome/browser/resources/hotword/training_manager.js
@@ -27,6 +27,47 @@ hotword.constants.SessionSource.TRAINING); } + /** + * Handles a success event on mounting the file system event. + * @param {FileSystem} fs The FileSystem object. + * @private + */ + TrainingManager.onRequestFileSystemSuccess_ = function(fs) { + fs.root.getFile(hotword.constants.SPEAKER_MODEL_FILE_NAME, {create: false}, + function(fileEntry) { + if (fileEntry.isFile) { + hotword.debug('File found: ' + fileEntry.fullPath); + if (hotword.DEBUG || window.localStorage['hotword.DEBUG']) { + fileEntry.getMetadata(function(md) { + hotword.debug('Speaker model file size: ' + md.size); + }); + } + fileEntry.remove(function() { + hotword.debug('File removed.'); + }, TrainingManager.fileErrorHandler_); + } + }, TrainingManager.fileErrorHandler_); + }; + + /** + * Handles a failure event on mounting the file system event. + * @param {FileError} e The FileError object. + * @private + */ + TrainingManager.fileErrorHandler_ = function(e) { + hotword.debug('File error: ' + e.code); + }; + + /** + * Handles a request to delete the speaker model. + */ + TrainingManager.handleDeleteSpeakerModel = function() { + window.webkitRequestFileSystem(PERSISTENT, + hotword.constants.FILE_SYSTEM_SIZE_BYTES, + TrainingManager.onRequestFileSystemSuccess_, + TrainingManager.fileErrorHandler_); + }; + TrainingManager.prototype = { __proto__: hotword.BaseSessionManager.prototype,
diff --git a/chrome/browser/resources/options/autofill_edit_overlay.css b/chrome/browser/resources/options/autofill_edit_overlay.css index 0c1f116..9f781319 100644 --- a/chrome/browser/resources/options/autofill_edit_overlay.css +++ b/chrome/browser/resources/options/autofill_edit_overlay.css
@@ -48,6 +48,17 @@ line-height: 2em; } +#autofill-edit-address-overlay list:not([has-element-focus]) > + [selected]:not(:hover) { + background-color: transparent; +} + +#autofill-edit-address-overlay list:not([has-element-focus]) > *:not(:hover) + .row-delete-button { + opacity: 0; + pointer-events: none; +} + :-webkit-any(#autofill-edit-credit-card-overlay, #autofill-edit-address-overlay) .settings-row label > :-webkit-any(input, select, textarea, list) { margin-top: 4px;
diff --git a/chrome/browser/resources/options/chromeos/internet_detail.html b/chrome/browser/resources/options/chromeos/internet_detail.html index 03354013..313dddb 100644 --- a/chrome/browser/resources/options/chromeos/internet_detail.html +++ b/chrome/browser/resources/options/chromeos/internet_detail.html
@@ -73,7 +73,8 @@ <span> <span i18n-content="inetPreferredNetwork"></span> <span class="controlled-setting-indicator" - managed="Priority"></span> + managed="Priority" + internet-detail-for="prefer-network-wifi"></span> </span> </label> </div> @@ -87,7 +88,9 @@ <span> <span i18n-content="inetAutoConnectNetwork"></span> <span class="controlled-setting-indicator" - managed="WiFi.AutoConnect"></span> + managed="WiFi.AutoConnect" + internet-detail-for="auto-connect-network-wifi"> + </span> </span> </label> </div> @@ -157,7 +160,9 @@ <span> <span i18n-content="inetAutoConnectNetwork"></span> <span class="controlled-setting-indicator" - managed="WiMAX.AutoConnect"></span> + managed="WiMAX.AutoConnect" + internet-detail-for="auto-connect-network-wimax"> + </span> </span> </label> </div> @@ -206,7 +211,8 @@ <span> <span i18n-content="inetAutoConnectNetwork"></span> <span class="controlled-setting-indicator" - managed="VPN.AutoConnect"></span> + managed="VPN.AutoConnect" + internet-detail-for="auto-connect-network-vpn"></span> </span> </label> </div> @@ -221,7 +227,8 @@ <td> <input class="option-value" id="inet-server-hostname"></input> <span class="controlled-setting-indicator" - managed="VPN.Host"></span> + managed="VPN.Host" + internet-detail-for="inet-server-hostname"></span> </td> </tr> <tr> @@ -283,7 +290,8 @@ </option> </select> <span class="controlled-setting-indicator" - managed="Cellular.APN"></span> + managed="Cellular.APN" + internet-detail-for="select-apn"></span> </td> </tr> <tr class="gsm-only apn-details-view"> @@ -323,7 +331,9 @@ <span> <span i18n-content="inetAutoConnectNetwork"></span> <span class="controlled-setting-indicator" - managed="Cellular.AutoConnect"></span> + managed="Cellular.AutoConnect" + internet-detail-for="auto-connect-network-cellular"> + </span> </span> </label> </div> @@ -501,7 +511,8 @@ <span> <span i18n-content="lockSimCard"></span> <span class="controlled-setting-indicator" - managed="Cellular.SIMLockStatus.LockEnabled"></span> + managed="Cellular.SIMLockStatus.LockEnabled" + internet-detail-for="sim-card-lock-enabled"></span> </span> </label> </div> @@ -510,7 +521,8 @@ <div id="change-pin-area"> <button id="change-pin" i18n-content="changePinButton"></button> <span class="controlled-setting-indicator" - managed="Cellular.SIMLockStatus.LockType"></span> + managed="Cellular.SIMLockStatus.LockType" + internet-detail-for="change-pin"></span> </div> </section> </div>
diff --git a/chrome/browser/resources/options/chromeos/internet_detail.js b/chrome/browser/resources/options/chromeos/internet_detail.js index 8477dd8..b433aac 100644 --- a/chrome/browser/resources/options/chromeos/internet_detail.js +++ b/chrome/browser/resources/options/chromeos/internet_detail.js
@@ -1639,7 +1639,7 @@ /** @type {{value: *, controlledBy: *, recommendedValue: *}} */( propValue)); indicators[i].handlePrefChange(event); - var forElement = $(indicators[i].getAttribute('for')); + var forElement = $(indicators[i].getAttribute('internet-detail-for')); if (forElement) { if (event.value.controlledBy == 'policy') forElement.disabled = true;
diff --git a/chrome/browser/resources/options/content_settings.html b/chrome/browser/resources/options/content_settings.html index 47aabc6..a429d099 100644 --- a/chrome/browser/resources/options/content_settings.html +++ b/chrome/browser/resources/options/content_settings.html
@@ -221,7 +221,7 @@ i18n-content="manageExceptions"></button> </div> <div id="disable-plugins-container"> - <a href="chrome://plugins" i18n-content="disableIndividualPlugins" + <a href="chrome://plugins" i18n-content="manageIndividualPlugins" target="_blank"></a> </div> </div>
diff --git a/chrome/browser/resources/pdf/elements/viewer-progress-bar/viewer-progress-bar.js b/chrome/browser/resources/pdf/elements/viewer-progress-bar/viewer-progress-bar.js index 0809cd6..97987cc 100644 --- a/chrome/browser/resources/pdf/elements/viewer-progress-bar/viewer-progress-bar.js +++ b/chrome/browser/resources/pdf/elements/viewer-progress-bar/viewer-progress-bar.js
@@ -14,7 +14,7 @@ var numVisible = this.progress * this.segments.length / 100.0; for (var i = 0; i < this.segments.length; i++) { this.segments[i].style.visibility = - i < numVisible ? 'auto' : 'hidden'; + i < numVisible ? 'inherit' : 'hidden'; } if (this.progress >= 100 || this.progress < 0)
diff --git a/chrome/browser/resources/pdf/index-material.html b/chrome/browser/resources/pdf/index-material.html index 21d76b06..2240d23 100644 --- a/chrome/browser/resources/pdf/index-material.html +++ b/chrome/browser/resources/pdf/index-material.html
@@ -53,10 +53,11 @@ <viewer-error-screen id="error-screen"></viewer-error-screen> </body> -<script src="main.js"></script> -<script src="pdf.js"></script> <script src="viewport.js"></script> <script src="open_pdf_params_parser.js"></script> +<script src="navigator.js"></script> <script src="pdf_scripting_api.js"></script> <script src="chrome://resources/js/util.js"></script> +<script src="pdf.js"></script> +<script src="main.js"></script> </html>
diff --git a/chrome/browser/resources/pdf/index.css b/chrome/browser/resources/pdf/index.css index 06ca8fc2..ed5a4ba 100644 --- a/chrome/browser/resources/pdf/index.css +++ b/chrome/browser/resources/pdf/index.css
@@ -34,9 +34,7 @@ } #plugin { - height: 100%; position: fixed; - width: 100%; z-index: 1; }
diff --git a/chrome/browser/resources/pdf/index.html b/chrome/browser/resources/pdf/index.html index 2f3df23..3ef308f 100644 --- a/chrome/browser/resources/pdf/index.html +++ b/chrome/browser/resources/pdf/index.html
@@ -51,6 +51,7 @@ </body> <script src="viewport.js"></script> <script src="open_pdf_params_parser.js"></script> +<script src="navigator.js"></script> <script src="pdf_scripting_api.js"></script> <script src="chrome://resources/js/util.js"></script> <script src="pdf.js"></script>
diff --git a/chrome/browser/resources/pdf/manifest-common.json.unflattened b/chrome/browser/resources/pdf/manifest-common.json.unflattened index 1f7eb2d..25354b6 100644 --- a/chrome/browser/resources/pdf/manifest-common.json.unflattened +++ b/chrome/browser/resources/pdf/manifest-common.json.unflattened
@@ -7,11 +7,7 @@ "offline_enabled": true, "incognito": "split", "permissions": [ - "file://*/", - "ftp://*/", - "http://*/", - "https://*/", - "chrome://*/" + "<all_urls>" ], "mime_types": [ "application/pdf"
diff --git a/chrome/browser/resources/pdf/navigator.js b/chrome/browser/resources/pdf/navigator.js new file mode 100644 index 0000000..b07c98cd --- /dev/null +++ b/chrome/browser/resources/pdf/navigator.js
@@ -0,0 +1,80 @@ +// Copyright 2015 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. + +'use strict'; + +/** + * Creates a new Navigator for navigating to links inside or outside the PDF. + * @param {string} originalUrl The original page URL. + * @param {Object} viewport The viewport info of the page. + * @param {Object} paramsParser The object for URL parsing. + */ +function Navigator(originalUrl, viewport, paramsParser) { + this.originalUrl_ = originalUrl; + this.viewport_ = viewport; + this.paramsParser_ = paramsParser; +} + +Navigator.prototype = { + /** + * @private + * Function to navigate to the given URL. This might involve navigating + * within the PDF page or opening a new url (in the same tab or a new tab). + * @param {string} url The URL to navigate to. + * @param {boolean} newTab Whether to perform the navigation in a new tab or + * in the current tab. + */ + navigate: function(url, newTab) { + if (url.length == 0) + return; + // If |urlFragment| starts with '#', then it's for the same URL with a + // different URL fragment. + if (url.charAt(0) == '#') { + // if '#' is already present in |originalUrl| then remove old fragment + // and add new url fragment. + var hashIndex = this.originalUrl_.search('#'); + if (hashIndex != -1) + url = this.originalUrl_.substring(0, hashIndex) + url; + else + url = this.originalUrl_ + url; + } + + // If there's no scheme, add http. + if (url.indexOf('://') == -1 && url.indexOf('mailto:') == -1) + url = 'http://' + url; + + // Make sure inputURL starts with a valid scheme. + if (url.indexOf('http://') != 0 && + url.indexOf('https://') != 0 && + url.indexOf('ftp://') != 0 && + url.indexOf('file://') != 0 && + url.indexOf('mailto:') != 0) { + return; + } + // Make sure inputURL is not only a scheme. + if (url == 'http://' || + url == 'https://' || + url == 'ftp://' || + url == 'file://' || + url == 'mailto:') { + return; + } + + if (newTab) { + // Prefer the tabs API because it guarantees we can just open a new tab. + // window.open doesn't have this guarantee. + if (chrome.tabs) + chrome.tabs.create({ url: url }); + else + window.open(url); + } else { + var pageNumber = + this.paramsParser_.getViewportFromUrlParams(url).page; + if (pageNumber != undefined) + this.viewport_.goToPage(pageNumber); + else + window.location.href = url; + } + } +};
diff --git a/chrome/browser/resources/pdf/open_pdf_params_parser.js b/chrome/browser/resources/pdf/open_pdf_params_parser.js index a0c7e0d..c0f4b19 100644 --- a/chrome/browser/resources/pdf/open_pdf_params_parser.js +++ b/chrome/browser/resources/pdf/open_pdf_params_parser.js
@@ -7,9 +7,8 @@ /** * Creates a new OpenPDFParamsParser. This parses the open pdf parameters * passed in the url to set initial viewport settings for opening the pdf. - * @param {string} url to be parsed. */ -function OpenPDFParamsParser(url) { +function OpenPDFParamsParser() { // A dictionary of all the named destinations in the PDF. this.namedDestinations = {}; }
diff --git a/chrome/browser/resources/pdf/pdf.js b/chrome/browser/resources/pdf/pdf.js index b2969e4..202b2798 100644 --- a/chrome/browser/resources/pdf/pdf.js +++ b/chrome/browser/resources/pdf/pdf.js
@@ -86,11 +86,9 @@ this.plugin_.type = 'application/x-google-chrome-pdf'; this.plugin_.addEventListener('message', this.handlePluginMessage_.bind(this), false); - if (this.isMaterial_) { - this.plugin_.style.height = + this.plugin_.style.height = (window.innerHeight - this.toolbarHeight_) + 'px'; - this.plugin_.style.width = window.innerWidth + 'px'; - } + this.plugin_.style.width = window.innerWidth + 'px'; // Handle scripting messages from outside the extension that wish to interact // with it. We also send a message indicating that extension has loaded and @@ -153,6 +151,8 @@ // Parse open pdf parameters. this.paramsParser_ = new OpenPDFParamsParser(); + this.navigator_ = new Navigator(this.streamDetails_.originalUrl, + this.viewport_, this.paramsParser_); } PDFViewer.prototype = { @@ -362,68 +362,6 @@ /** * @private - * Helper function to navigate to given URL. This might involve navigating - * within the PDF page or opening a new url (in the same tab or a new tab). - * @param {string} url The URL to navigate to. - * @param {boolean} newTab Whether to perform the navigation in a new tab or - * in the current tab. - */ - navigate_: function(url, newTab) { - if (url.length == 0) - return; - var originalUrl = this.streamDetails_.originalUrl; - // If |urlFragment| starts with '#', then it's for the same URL with a - // different URL fragment. - if (url.charAt(0) == '#') { - // if '#' is already present in |originalUrl| then remove old fragment - // and add new url fragment. - var hashIndex = originalUrl.search('#'); - if (hashIndex != -1) - url = originalUrl.substring(0, hashIndex) + url; - else - url = originalUrl + url; - } - - // If there's no scheme, add http. - if (url.indexOf('://') == -1 && url.indexOf('mailto:') == -1) - url = 'http://' + url; - - // Make sure url starts with a valid scheme. - if (url.indexOf('http://') != 0 && - url.indexOf('https://') != 0 && - url.indexOf('ftp://') != 0 && - url.indexOf('file://') != 0 && - url.indexOf('mailto:') != 0) { - return; - } - // Make sure url is not only a scheme. - if (url == 'http://' || - url == 'https://' || - url == 'ftp://' || - url == 'file://' || - url == 'mailto:') { - return; - } - - if (newTab) { - // Prefer the tabs API because it guarantees we can just open a new tab. - // window.open doesn't have this guarantee. - if (chrome.tabs) - chrome.tabs.create({ url: url }); - else - window.open(url); - } else { - var pageNumber = - this.paramsParser_.getViewportFromUrlParams(url).page; - if (pageNumber != undefined) - this.viewport_.goToPage(pageNumber); - else - window.location.href = url; - } - }, - - /** - * @private * An event handler for handling message events received from the plugin. * @param {MessageObject} message a message event. */ @@ -471,7 +409,7 @@ if (this.isPrintPreview_) this.navigate_(message.data.url, true); else - this.navigate_(message.data.url, message.data.newTab); + this.navigator_.navigate(message.data.url, message.data.newTab); break; case 'setNamedDestinations': this.paramsParser_.namedDestinations = message.data.namedDestinations; @@ -555,15 +493,19 @@ * A callback that's called after the viewport changes. */ viewportChanged_: function() { + var hasScrollbars = this.viewport_.documentHasScrollbars(); + var scrollbarWidth = this.viewport_.scrollbarWidth; + var verticalScrollbarWidth = hasScrollbars.vertical ? scrollbarWidth : 0; + var horizontalScrollbarWidth = + hasScrollbars.horizontal ? scrollbarWidth : 0; + this.plugin_.style.width = + (window.innerWidth - verticalScrollbarWidth) + 'px'; + this.plugin_.style.height = (window.innerHeight - + horizontalScrollbarWidth - this.toolbarHeight_) + 'px'; + if (!this.documentDimensions_) return; - if (this.isMaterial_) { - this.plugin_.style.height = - (window.innerHeight - this.toolbarHeight_) + 'px'; - this.plugin_.style.width = window.innerWidth + 'px'; - } - // Update the buttons selected. $('fit-to-page-button').classList.remove('polymer-selected'); $('fit-to-width-button').classList.remove('polymer-selected'); @@ -574,15 +516,11 @@ $('fit-to-width-button').classList.add('polymer-selected'); } - var hasScrollbars = this.viewport_.documentHasScrollbars(); - var scrollbarWidth = this.viewport_.scrollbarWidth; // Offset the toolbar position so that it doesn't move if scrollbars appear. var toolbarRight = Math.max(PDFViewer.MIN_TOOLBAR_OFFSET, scrollbarWidth); var toolbarBottom = Math.max(PDFViewer.MIN_TOOLBAR_OFFSET, scrollbarWidth); - if (hasScrollbars.vertical) - toolbarRight -= scrollbarWidth; - if (hasScrollbars.horizontal) - toolbarBottom -= scrollbarWidth; + toolbarRight -= verticalScrollbarWidth; + toolbarBottom -= horizontalScrollbarWidth; this.toolbar_.style.right = toolbarRight + 'px'; this.toolbar_.style.bottom = toolbarBottom + 'px'; // Hide the toolbar if it doesn't fit in the viewport. @@ -732,5 +670,16 @@ */ get viewport() { return this.viewport_; + }, + + /** + * Each bookmark is an Object containing a: + * - title + * - page (optional) + * - array of children (themselves bookmarks) + * @type {Array} the top-level bookmarks of the PDF. + */ + get bookmarks() { + return this.bookmarks_; } };
diff --git a/chrome/browser/resources/pdf/pdf_extension_test.cc b/chrome/browser/resources/pdf/pdf_extension_test.cc index e7fcffb..699669f7 100644 --- a/chrome/browser/resources/pdf/pdf_extension_test.cc +++ b/chrome/browser/resources/pdf/pdf_extension_test.cc
@@ -40,7 +40,7 @@ ExtensionApiTest::TearDownOnMainThread(); } - void RunTestsInFile(std::string filename) { + void RunTestsInFile(std::string filename, std::string pdf_filename) { base::FilePath pdf_path; ASSERT_TRUE(PathService::Get(chrome::FILE_PDF_PLUGIN, &pdf_path)); ASSERT_TRUE( @@ -60,7 +60,7 @@ extensions::ResultCatcher catcher; - GURL url(embedded_test_server()->GetURL("/pdf/test.pdf")); + GURL url(embedded_test_server()->GetURL("/pdf/" + pdf_filename)); GURL extension_url( "chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/index.html?" + url.spec()); @@ -85,13 +85,17 @@ }; IN_PROC_BROWSER_TEST_F(PDFExtensionTest, Basic) { - RunTestsInFile("basic_test.js"); + RunTestsInFile("basic_test.js", "test.pdf"); } IN_PROC_BROWSER_TEST_F(PDFExtensionTest, BasicPlugin) { - RunTestsInFile("basic_plugin_test.js"); + RunTestsInFile("basic_plugin_test.js", "test.pdf"); } IN_PROC_BROWSER_TEST_F(PDFExtensionTest, Viewport) { - RunTestsInFile("viewport_test.js"); + RunTestsInFile("viewport_test.js", "test.pdf"); +} + +IN_PROC_BROWSER_TEST_F(PDFExtensionTest, Bookmark) { + RunTestsInFile("bookmarks_test.js", "test-bookmarks.pdf"); }
diff --git a/chrome/browser/resources/print_preview/previewarea/margin_control_container.js b/chrome/browser/resources/print_preview/previewarea/margin_control_container.js index ceab20b..af9d3fa 100644 --- a/chrome/browser/resources/print_preview/previewarea/margin_control_container.js +++ b/chrome/browser/resources/print_preview/previewarea/margin_control_container.js
@@ -14,11 +14,15 @@ * Used to read and write custom margin values. * @param {!print_preview.MeasurementSystem} measurementSystem Used to convert * between the system's local units and points. + * @param {function(boolean)} dragChangedCallback A function which is called + * when dragging margins starts or stops. True is passed to the function + * if the margin is currently being dragged and false otherwise. * @constructor * @extends {print_preview.Component} */ function MarginControlContainer(documentInfo, marginsTypeTicketItem, - customMarginsTicketItem, measurementSystem) { + customMarginsTicketItem, measurementSystem, + dragChangedCallback) { print_preview.Component.call(this); /** @@ -48,6 +52,15 @@ this.measurementSystem_ = measurementSystem; /** + * Called in response to dragging the margins starting or stopping. True is + * passed to the function if the margin is currently being dragged and false + * otherwise. + * @type {function(boolean)} + * @private + */ + this.dragChangedCallback_ = dragChangedCallback; + + /** * Convenience array that contains all of the margin controls. * @type {!Object.< * !print_preview.ticket_items.CustomMargins.Orientation, @@ -307,6 +320,7 @@ MarginControlContainer.isTopOrBottom_(control.getOrientation()) ? MarginControlContainer.Classes_.DRAGGING_VERTICAL : MarginControlContainer.Classes_.DRAGGING_HORIZONTAL); + this.dragChangedCallback_(true); }, /** @@ -348,6 +362,7 @@ this.draggedControl_.getOrientation(), this.draggedControl_.getPositionInPts()); this.draggedControl_ = null; + this.dragChangedCallback_(false); } },
diff --git a/chrome/browser/resources/print_preview/previewarea/preview_area.js b/chrome/browser/resources/print_preview/previewarea/preview_area.js index 8a33f4ec..ca06dd84 100644 --- a/chrome/browser/resources/print_preview/previewarea/preview_area.js +++ b/chrome/browser/resources/print_preview/previewarea/preview_area.js
@@ -108,7 +108,8 @@ this.documentInfo_, this.printTicketStore_.marginsType, this.printTicketStore_.customMargins, - this.printTicketStore_.measurementSystem); + this.printTicketStore_.measurementSystem, + this.onMarginDragChanged_.bind(this)); this.addChild(this.marginControlContainer_); /** @@ -793,6 +794,22 @@ this.marginControlContainer_.updateClippingMask( new print_preview.Size(viewportWidth, viewportHeight)); } + }, + + /** + * Called when dragging margins starts or stops. + * @param {boolean} isDragging True if the margin is currently being dragged + * and false otherwise. + */ + onMarginDragChanged_: function(isDragging) { + if (!this.plugin_) + return; + + // When hovering over the plugin (which may be in a separate iframe) + // pointer events will be sent to the frame. When dragging the margins, + // we don't want this to happen as it can cause the margin to stop + // being draggable. + this.plugin_.style.pointerEvents = isDragging ? 'none' : 'auto'; } };
diff --git a/chrome/browser/resources/security_warnings/interstitial_v2.html b/chrome/browser/resources/security_warnings/interstitial_v2.html index 245bf0d..0b384dc 100644 --- a/chrome/browser/resources/security_warnings/interstitial_v2.html +++ b/chrome/browser/resources/security_warnings/interstitial_v2.html
@@ -12,9 +12,7 @@ <script src="safe_browsing.js"></script> <script src="interstitial_v2.js"></script> </head> -<!-- TODO(jshin): Get rid of i18n-values and import default_text.css instead - once interstitial page loading does not use data url any more. --> -<body id="body" i18n-values=".style.fontFamily:fontfamily;.style.fontSize:fontsize"> +<body id="body"> <div class="interstitial-wrapper"> <div class="icon" id="icon"></div> <div id="main-message">
diff --git a/chrome/browser/resources/supervised_user_block_interstitial.html b/chrome/browser/resources/supervised_user_block_interstitial.html index a242583..18a9059 100644 --- a/chrome/browser/resources/supervised_user_block_interstitial.html +++ b/chrome/browser/resources/supervised_user_block_interstitial.html
@@ -11,9 +11,7 @@ <script src="supervised_user_block_interstitial.js"></script> </head> -<!-- TODO(jshin): Get rid of i18n-values and import default_text.css instead - once interstitial page loading does not use data url any more. --> -<body i18n-values=".style.fontFamily:fontfamily"> +<body> <div id="main-frame-blocked"> <div id="box"> <div id="content-top">
diff --git a/chrome/browser/resources/user_manager/user_manager.css b/chrome/browser/resources/user_manager/user_manager.css index 67b3336fa..babcbb91 100644 --- a/chrome/browser/resources/user_manager/user_manager.css +++ b/chrome/browser/resources/user_manager/user_manager.css
@@ -29,7 +29,15 @@ transform: scale(0.8); } +/* Because of crbug.com/406529, the text in the .name div is janky if there's +both a transform:scale and a transition:opacity applied to a div, so we must +apply the opacity change to the children instead. */ .pod.faded { + opacity: 1; +} + +.pod.faded .user-image-pane, +.pod.faded .main-pane { opacity: .4; }
diff --git a/chrome/browser/rlz/rlz_unittest.cc b/chrome/browser/rlz/rlz_unittest.cc index 5560a2f..0a0f7a2 100644 --- a/chrome/browser/rlz/rlz_unittest.cc +++ b/chrome/browser/rlz/rlz_unittest.cc
@@ -137,7 +137,7 @@ } #if defined(OS_CHROMEOS) - virtual bool ScheduleClearRlzState() override { + bool ScheduleClearRlzState() override { return !assume_not_ui_thread_; } #endif @@ -251,7 +251,7 @@ // with empty or invalid values. AutocompleteResult empty_result; OmniboxLog dummy(base::string16(), false, metrics::OmniboxInputType::INVALID, - true, 0, false, false, -1, + true, 0, false, -1, metrics::OmniboxEventProto::INVALID_SPEC, base::TimeDelta::FromSeconds(0), 0, base::TimeDelta::FromSeconds(0),
diff --git a/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service.cc b/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service.cc index 71df77e3..236aae4 100644 --- a/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service.cc +++ b/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service.cc
@@ -27,7 +27,6 @@ #include "chrome/browser/safe_browsing/incident_reporting/environment_data_collection.h" #include "chrome/browser/safe_browsing/incident_reporting/incident.h" #include "chrome/browser/safe_browsing/incident_reporting/incident_report_uploader_impl.h" -#include "chrome/browser/safe_browsing/incident_reporting/omnibox_watcher.h" #include "chrome/browser/safe_browsing/incident_reporting/preference_validation_delegate.h" #include "chrome/browser/safe_browsing/safe_browsing_service.h" #include "chrome/common/pref_names.h" @@ -156,9 +155,6 @@ // Will contain null values for pruned incidents. ScopedVector<Incident> incidents; - // Watches for suspicious omnibox interactions on this profile. - scoped_ptr<OmniboxWatcher> omnibox_watcher; - // False until PROFILE_ADDED notification is received. bool added; @@ -364,11 +360,6 @@ // so that the service can determine whether or not it can evaluate a // profile's preferences at the time of incident addition. ProfileContext* context = GetOrCreateProfileContext(profile); - // Start watching the profile now if necessary. - if (!context->omnibox_watcher) { - context->omnibox_watcher.reset( - new OmniboxWatcher(profile, GetAddIncidentCallback(profile))); - } context->added = true; const bool safe_browsing_enabled =
diff --git a/chrome/browser/safe_browsing/incident_reporting/omnibox_interaction_incident.cc b/chrome/browser/safe_browsing/incident_reporting/omnibox_interaction_incident.cc deleted file mode 100644 index 63fe9934..0000000 --- a/chrome/browser/safe_browsing/incident_reporting/omnibox_interaction_incident.cc +++ /dev/null
@@ -1,39 +0,0 @@ -// Copyright 2015 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/safe_browsing/incident_reporting/omnibox_interaction_incident.h" - -#include "base/logging.h" -#include "chrome/common/safe_browsing/csd.pb.h" - -namespace safe_browsing { - -OmniboxInteractionIncident::OmniboxInteractionIncident( - scoped_ptr<ClientIncidentReport_IncidentData_OmniboxInteractionIncident> - omnibox_interaction_incident) { - DCHECK(omnibox_interaction_incident); - DCHECK(omnibox_interaction_incident->has_origin()); - payload()->set_allocated_omnibox_interaction( - omnibox_interaction_incident.release()); -} - -OmniboxInteractionIncident::~OmniboxInteractionIncident() { -} - -IncidentType OmniboxInteractionIncident::GetType() const { - return IncidentType::OMNIBOX_INTERACTION; -} - -std::string OmniboxInteractionIncident::GetKey() const { - // Return a constant, as only one kind of suspicious interaction is detected. - return "1"; -} - -uint32_t OmniboxInteractionIncident::ComputeDigest() const { - // Return a constant (independent of the incident's payload) so that only the - // first suspicious interaction is reported. - return 1u; -} - -} // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/incident_reporting/omnibox_interaction_incident.h b/chrome/browser/safe_browsing/incident_reporting/omnibox_interaction_incident.h deleted file mode 100644 index 4f38cea..0000000 --- a/chrome/browser/safe_browsing/incident_reporting/omnibox_interaction_incident.h +++ /dev/null
@@ -1,34 +0,0 @@ -// Copyright 2015 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_SAFE_BROWSING_INCIDENT_REPORTING_OMNIBOX_INTERACTION_INCIDENT_H_ -#define CHROME_BROWSER_SAFE_BROWSING_INCIDENT_REPORTING_OMNIBOX_INTERACTION_INCIDENT_H_ - -#include "base/memory/scoped_ptr.h" -#include "chrome/browser/safe_browsing/incident_reporting/incident.h" - -namespace safe_browsing { - -class ClientIncidentReport_IncidentData_OmniboxInteractionIncident; - -// An incident representing a suspicious omnibox interaction. -class OmniboxInteractionIncident : public Incident { - public: - explicit OmniboxInteractionIncident( - scoped_ptr<ClientIncidentReport_IncidentData_OmniboxInteractionIncident> - omnibox_interaction); - ~OmniboxInteractionIncident() override; - - // Incident methods: - IncidentType GetType() const override; - std::string GetKey() const override; - uint32_t ComputeDigest() const override; - - private: - DISALLOW_COPY_AND_ASSIGN(OmniboxInteractionIncident); -}; - -} // namespace safe_browsing - -#endif // CHROME_BROWSER_SAFE_BROWSING_INCIDENT_REPORTING_OMNIBOX_INTERACTION_INCIDENT_H_
diff --git a/chrome/browser/safe_browsing/incident_reporting/omnibox_watcher.cc b/chrome/browser/safe_browsing/incident_reporting/omnibox_watcher.cc deleted file mode 100644 index e0216ac..0000000 --- a/chrome/browser/safe_browsing/incident_reporting/omnibox_watcher.cc +++ /dev/null
@@ -1,56 +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 "chrome/browser/safe_browsing/incident_reporting/omnibox_watcher.h" - -#include "base/time/time.h" -#include "chrome/browser/chrome_notification_types.h" -#include "chrome/browser/omnibox/omnibox_log.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/safe_browsing/incident_reporting/omnibox_interaction_incident.h" -#include "chrome/common/safe_browsing/csd.pb.h" -#include "components/omnibox/autocomplete_result.h" -#include "content/public/browser/notification_details.h" -#include "content/public/browser/notification_service.h" - -namespace safe_browsing { - -OmniboxWatcher::OmniboxWatcher(Profile* profile, - const AddIncidentCallback& callback): - incident_callback_(callback) { - registrar_.Add(this, chrome::NOTIFICATION_OMNIBOX_OPENED_URL, - content::Source<Profile>(profile)); -} - -OmniboxWatcher::~OmniboxWatcher() { -} - -void OmniboxWatcher::Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) { - DCHECK_EQ(chrome::NOTIFICATION_OMNIBOX_OPENED_URL, type); - const OmniboxLog* log = content::Details<OmniboxLog>(details).ptr(); - const AutocompleteMatch& selected_suggestion = - log->result.match_at(log->selected_index); - // Users tend not to type very long strings explicitly (especially without - // using the paste-and-go option), and certainly not in under a second. - // No normal person can type URLs that fast! Navigating to a URL as a - // result of such typing is suspicious. - // TODO(mpearson): Add support for suspicious queries. - if (!log->is_paste_and_go && !log->last_action_was_paste && - log->is_popup_open && (log->text.length() > 200) && - (log->elapsed_time_since_user_first_modified_omnibox < - base::TimeDelta::FromSeconds(1)) && - !AutocompleteMatch::IsSearchType(selected_suggestion.type)) { - scoped_ptr<ClientIncidentReport_IncidentData_OmniboxInteractionIncident> - omnibox_interaction( - new ClientIncidentReport_IncidentData_OmniboxInteractionIncident()); - const GURL& origin = selected_suggestion.destination_url.GetOrigin(); - omnibox_interaction->set_origin(origin.possibly_invalid_spec()); - incident_callback_.Run(make_scoped_ptr( - new OmniboxInteractionIncident(omnibox_interaction.Pass()))); - } -} - -} // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/incident_reporting/omnibox_watcher.h b/chrome/browser/safe_browsing/incident_reporting/omnibox_watcher.h deleted file mode 100644 index 5966892..0000000 --- a/chrome/browser/safe_browsing/incident_reporting/omnibox_watcher.h +++ /dev/null
@@ -1,43 +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 CHROME_BROWSER_SAFE_BROWSING_INCIDENT_REPORTING_OMNIBOX_WATCHER_H_ -#define CHROME_BROWSER_SAFE_BROWSING_INCIDENT_REPORTING_OMNIBOX_WATCHER_H_ - -#include "base/callback.h" -#include "base/macros.h" -#include "chrome/browser/safe_browsing/incident_reporting/add_incident_callback.h" -#include "content/public/browser/notification_observer.h" -#include "content/public/browser/notification_registrar.h" - -class Profile; - -namespace safe_browsing { - -// Observes all URLs opened via the omnibox, adding an incident to the -// incident reporting service for those that are typed impossibly quickly. -class OmniboxWatcher : public content::NotificationObserver { - public: - OmniboxWatcher(Profile* profile, const AddIncidentCallback& callback); - ~OmniboxWatcher() override; - - private: - // content::NotificationObserver: - void Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) override; - - // The place to send a callback when we witness a suspicious omnibox - // navigation. - AddIncidentCallback incident_callback_; - - // Registrar for receiving Omnibox event notifications. - content::NotificationRegistrar registrar_; - - DISALLOW_COPY_AND_ASSIGN(OmniboxWatcher); -}; - -} // namespace safe_browsing - -#endif // CHROME_BROWSER_SAFE_BROWSING_INCIDENT_REPORTING_OMNIBOX_WATCHER_H_
diff --git a/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc b/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc index 5b053b1c..0515ecd 100644 --- a/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc +++ b/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc
@@ -220,6 +220,13 @@ if (command.length() > 1 && command[0] == '"') { command = command.substr(1, command.length() - 2); } + + if (command == "pageLoadComplete") { + // content::WaitForRenderFrameReady sends this message when the page + // load completes. Ignore it. + return; + } + if (command == kDoReportCommand) { SetReportingPreference(true); return;
diff --git a/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc b/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc index 9bb0809b..bd22f4b 100644 --- a/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc +++ b/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc
@@ -512,20 +512,11 @@ } bool WaitForReady() { - content::RenderViewHost* rvh = GetRenderViewHost(); - if (!rvh) + InterstitialPage* interstitial = InterstitialPage::GetInterstitialPage( + browser()->tab_strip_model()->GetActiveWebContents()); + if (!interstitial) return false; - // Wait until all <script> tags have executed, including jstemplate. - // TODO(joaodasilva): it would be nice to avoid the busy loop, though in - // practice it spins at most once or twice. - std::string ready_state; - do { - scoped_ptr<base::Value> value = content::ExecuteScriptAndGetValue( - rvh->GetMainFrame(), "document.readyState"); - if (!value.get() || !value->GetAsString(&ready_state)) - return false; - } while (ready_state != "complete"); - return true; + return content::WaitForRenderFrameReady(interstitial->GetMainFrame()); } Visibility GetVisibility(const std::string& node_id) {
diff --git a/chrome/browser/search/hotword_audio_history_handler.cc b/chrome/browser/search/hotword_audio_history_handler.cc index 70dfd657..d6c6384b 100644 --- a/chrome/browser/search/hotword_audio_history_handler.cc +++ b/chrome/browser/search/hotword_audio_history_handler.cc
@@ -97,9 +97,18 @@ if (success) { value = new_enabled_value; prefs->SetBoolean(prefs::kHotwordAudioLoggingEnabled, value); - // If the setting is now turned off, always on should also be turned off. - if (!value) - prefs->SetBoolean(prefs::kHotwordAlwaysOnSearchEnabled, false); + // If the setting is now turned off, always on should also be turned off, + // and the speaker model should be deleted. + if (!value) { + if (prefs->GetBoolean(prefs::kHotwordAlwaysOnSearchEnabled)) { + prefs->SetBoolean(prefs::kHotwordAlwaysOnSearchEnabled, false); + HotwordPrivateEventService* event_service = + BrowserContextKeyedAPIFactory<HotwordPrivateEventService>::Get( + profile_); + if (event_service) + event_service->OnDeleteSpeakerModel(); + } + } } callback.Run(success, value); }
diff --git a/chrome/browser/search/hotword_service.cc b/chrome/browser/search/hotword_service.cc index b566a44a..5a02b4c 100644 --- a/chrome/browser/search/hotword_service.cc +++ b/chrome/browser/search/hotword_service.cc
@@ -424,7 +424,6 @@ l10n_util::GetStringUTF16(IDS_HOTWORD_NOTIFICATION_DESCRIPTION), ui::ResourceBundle::GetSharedInstance().GetImageNamed( IDR_HOTWORD_NOTIFICATION_ICON), - blink::WebTextDirectionDefault, message_center::NotifierId( message_center::NotifierId::SYSTEM_COMPONENT, hotword_internal::kHotwordNotifierId),
diff --git a/chrome/browser/search/hotword_service_factory.cc b/chrome/browser/search/hotword_service_factory.cc index 174f375a..8884ad6 100644 --- a/chrome/browser/search/hotword_service_factory.cc +++ b/chrome/browser/search/hotword_service_factory.cc
@@ -47,9 +47,6 @@ // static bool HotwordServiceFactory::IsHotwordHardwareAvailable() { -// Temporarily disabling hotword hardware check for M41. Will be -// re-enabled for M42. -#if 0 #if defined(OS_CHROMEOS) if (chromeos::CrasAudioHandler::IsInitialized()) { chromeos::AudioDeviceList devices; @@ -62,7 +59,6 @@ } } #endif -#endif // 0 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); return command_line->HasSwitch(switches::kEnableExperimentalHotwordHardware); }
diff --git a/chrome/browser/service_process/service_process_control_browsertest.cc b/chrome/browser/service_process/service_process_control_browsertest.cc index eb934c8..097b8f59 100644 --- a/chrome/browser/service_process/service_process_control_browsertest.cc +++ b/chrome/browser/service_process/service_process_control_browsertest.cc
@@ -9,7 +9,7 @@ #include "base/command_line.h" #include "base/path_service.h" #include "base/process/kill.h" -#include "base/process/process_handle.h" +#include "base/process/process.h" #include "base/process/process_iterator.h" #include "base/test/test_timeouts.h" #include "chrome/browser/ui/browser.h" @@ -25,12 +25,9 @@ class ServiceProcessControlBrowserTest : public InProcessBrowserTest { public: - ServiceProcessControlBrowserTest() - : service_process_handle_(base::kNullProcessHandle) { + ServiceProcessControlBrowserTest() { } virtual ~ServiceProcessControlBrowserTest() { - base::CloseProcessHandle(service_process_handle_); - service_process_handle_ = base::kNullProcessHandle; } void HistogramsCallback() { @@ -69,7 +66,10 @@ } virtual void SetUp() override { - service_process_handle_ = base::kNullProcessHandle; + // This should not be needed because TearDown() ends with a closed + // service_process_, but HistogramsTimeout and Histograms fail without this + // on Mac. + service_process_.Close(); } virtual void TearDown() override { @@ -79,11 +79,11 @@ // ForceServiceProcessShutdown removes the process from launched on Mac. ForceServiceProcessShutdown("", 0); #endif // OS_MACOSX - if (service_process_handle_ != base::kNullProcessHandle) { + if (service_process_.IsValid()) { EXPECT_TRUE(base::WaitForSingleProcess( - service_process_handle_, + service_process_.Handle(), TestTimeouts::action_max_timeout())); - service_process_handle_ = base::kNullProcessHandle; + service_process_.Close(); } } @@ -91,12 +91,16 @@ base::ProcessId service_pid; EXPECT_TRUE(GetServiceProcessData(NULL, &service_pid)); EXPECT_NE(static_cast<base::ProcessId>(0), service_pid); - EXPECT_TRUE(base::OpenProcessHandleWithAccess( - service_pid, - base::kProcessAccessWaitForTermination | - // we need query permission to get exit code - base::kProcessAccessQueryInformation, - &service_process_handle_)); +#if defined(OS_WIN) + service_process_ = + base::Process::OpenWithAccess(service_pid, + SYNCHRONIZE | PROCESS_QUERY_INFORMATION); + EXPECT_TRUE(service_process_.IsValid()); +#else + base::ProcessHandle service_process_handle; + EXPECT_TRUE(base::OpenProcessHandle(service_pid, &service_process_handle)); + service_process_ = base::Process(service_process_handle); +#endif // Quit the current message. Post a QuitTask instead of just calling Quit() // because this can get invoked in the context of a Launch() call and we // may not be in Run() yet. @@ -112,7 +116,7 @@ } private: - base::ProcessHandle service_process_handle_; + base::Process service_process_; }; class RealServiceProcessControlBrowserTest
diff --git a/chrome/browser/services/gcm/gcm_account_tracker.cc b/chrome/browser/services/gcm/gcm_account_tracker.cc index 0521688..22dd5b5 100644 --- a/chrome/browser/services/gcm/gcm_account_tracker.cc +++ b/chrome/browser/services/gcm/gcm_account_tracker.cc
@@ -150,8 +150,13 @@ iter->second.state == ACCOUNT_REMOVED); // If OnAccountSignedOut(..) was called most recently, account is kept in // ACCOUNT_REMOVED state. - if (iter->second.state == GETTING_TOKEN) - iter->second.state = TOKEN_NEEDED; + if (iter->second.state == GETTING_TOKEN) { + // Given the fetcher has a built in retry logic, consider this situation + // to be invalid refresh token, that is only fixed when user signs in. + // Once the users signs in properly the minting will retry. + iter->second.access_token.clear(); + iter->second.state = ACCOUNT_REMOVED; + } } DeleteTokenRequest(request);
diff --git a/chrome/browser/services/gcm/gcm_account_tracker_unittest.cc b/chrome/browser/services/gcm/gcm_account_tracker_unittest.cc index eb8030a1..2093f6b 100644 --- a/chrome/browser/services/gcm/gcm_account_tracker_unittest.cc +++ b/chrome/browser/services/gcm/gcm_account_tracker_unittest.cc
@@ -359,16 +359,13 @@ EXPECT_FALSE(driver()->update_accounts_called()); IssueError(kAccountId2); - EXPECT_FALSE(driver()->update_accounts_called()); - EXPECT_EQ(1UL, tracker()->get_pending_token_request_count()); - - IssueAccessToken(kAccountId2); + // Failed token is not retried any more. Account marked as removed. + EXPECT_EQ(0UL, tracker()->get_pending_token_request_count()); EXPECT_TRUE(driver()->update_accounts_called()); std::vector<GCMClient::AccountTokenInfo> expected_accounts; expected_accounts.push_back(MakeAccountToken(kAccountId1)); - expected_accounts.push_back(MakeAccountToken(kAccountId2)); VerifyAccountTokens(expected_accounts, driver()->accounts()); } @@ -378,7 +375,6 @@ tracker()->Start(); IssueAccessToken(kAccountId1); - IssueError(kAccountId2); driver()->ResetResults(); SignOutAccount(kAccountId2);
diff --git a/chrome/browser/services/gcm/gcm_app_handler.h b/chrome/browser/services/gcm/gcm_app_handler.h deleted file mode 100644 index b5a9e06..0000000 --- a/chrome/browser/services/gcm/gcm_app_handler.h +++ /dev/null
@@ -1,12 +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 CHROME_BROWSER_SERVICES_GCM_GCM_APP_HANDLER_H_ -#define CHROME_BROWSER_SERVICES_GCM_GCM_APP_HANDLER_H_ - -// Temporary workaround to make code depends on gcm_app_handler in old location -// build. -#include "components/gcm_driver/gcm_app_handler.h" - -#endif // CHROME_BROWSER_SERVICES_GCM_GCM_APP_HANDLER_H_
diff --git a/chrome/browser/sessions/better_session_restore_browsertest.cc b/chrome/browser/sessions/better_session_restore_browsertest.cc index 47997f7..b6c902602 100644 --- a/chrome/browser/sessions/better_session_restore_browsertest.cc +++ b/chrome/browser/sessions/better_session_restore_browsertest.cc
@@ -20,6 +20,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_impl.h" #include "chrome/browser/profiles/profile_manager.h" +#include "chrome/browser/sessions/session_restore_test_helper.h" #include "chrome/browser/sessions/session_service_factory.h" #include "chrome/browser/sessions/session_service_test_helper.h" #include "chrome/browser/ui/browser.h" @@ -377,9 +378,7 @@ protected: Browser* QuitBrowserAndRestore(Browser* browser, bool close_all_windows) override { - content::WindowedNotificationObserver session_restore_observer( - chrome::NOTIFICATION_SESSION_RESTORE_DONE, - content::NotificationService::AllSources()); + SessionRestoreTestHelper session_restore_observer; Browser* new_browser = BetterSessionRestoreTest::QuitBrowserAndRestore( browser, close_all_windows); session_restore_observer.Wait();
diff --git a/chrome/browser/sessions/session_restore_browsertest.cc b/chrome/browser/sessions/session_restore_browsertest.cc index e36de976..2f091caa 100644 --- a/chrome/browser/sessions/session_restore_browsertest.cc +++ b/chrome/browser/sessions/session_restore_browsertest.cc
@@ -17,6 +17,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/sessions/session_restore.h" +#include "chrome/browser/sessions/session_restore_test_helper.h" #include "chrome/browser/sessions/session_service.h" #include "chrome/browser/sessions/session_service_factory.h" #include "chrome/browser/sessions/session_service_test_helper.h" @@ -139,9 +140,7 @@ // Create a new window, which should trigger session restore. ui_test_utils::BrowserAddedObserver window_observer; - content::WindowedNotificationObserver restore_observer( - chrome::NOTIFICATION_SESSION_RESTORE_DONE, - content::NotificationService::AllSources()); + SessionRestoreTestHelper restore_observer; if (url.is_empty()) { chrome::NewEmptyWindow(profile, chrome::HOST_DESKTOP_TYPE_NATIVE); } else {
diff --git a/chrome/browser/sessions/session_restore_test_helper.cc b/chrome/browser/sessions/session_restore_test_helper.cc new file mode 100644 index 0000000..678ea99 --- /dev/null +++ b/chrome/browser/sessions/session_restore_test_helper.cc
@@ -0,0 +1,39 @@ +// Copyright 2015 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/sessions/session_restore_test_helper.h" + +#include "content/public/test/test_utils.h" +#include "testing/gtest/include/gtest/gtest.h" + +SessionRestoreTestHelper::SessionRestoreTestHelper() + : restore_notification_seen_(false), + loop_is_running_(false), + weak_ptr_factory(this) { + callback_subscription_ = SessionRestore::RegisterOnSessionRestoredCallback( + base::Bind(&SessionRestoreTestHelper::OnSessionRestoreDone, + weak_ptr_factory.GetWeakPtr())); +} + +SessionRestoreTestHelper::~SessionRestoreTestHelper() { +} + +void SessionRestoreTestHelper::Wait() { + if (restore_notification_seen_) + return; + + loop_is_running_ = true; + message_loop_runner_ = new content::MessageLoopRunner; + message_loop_runner_->Run(); + EXPECT_TRUE(restore_notification_seen_); +} + +void SessionRestoreTestHelper::OnSessionRestoreDone() { + restore_notification_seen_ = true; + if (!loop_is_running_) + return; + + message_loop_runner_->Quit(); + loop_is_running_ = false; +}
diff --git a/chrome/browser/sessions/session_restore_test_helper.h b/chrome/browser/sessions/session_restore_test_helper.h new file mode 100644 index 0000000..1e44d40 --- /dev/null +++ b/chrome/browser/sessions/session_restore_test_helper.h
@@ -0,0 +1,50 @@ +// Copyright 2015 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_SESSIONS_SESSION_RESTORE_TEST_HELPER_H_ +#define CHROME_BROWSER_SESSIONS_SESSION_RESTORE_TEST_HELPER_H_ + +#include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/weak_ptr.h" +#include "chrome/browser/sessions/session_restore.h" + +namespace content { +class MessageLoopRunner; +} + +// This class waits on the SessionRestore notification. It is a replacement for +// content::WindowedNotificationObserver, which uses notification service. This +// class uses the callback-based notification instead. +class SessionRestoreTestHelper { + public: + SessionRestoreTestHelper(); + ~SessionRestoreTestHelper(); + + // Blocks until OnSessionRestore() is called. + void Wait(); + + private: + // Callback for session restore notifications. + void OnSessionRestoreDone(); + + // Indicates whether a session restore notification has been received. + bool restore_notification_seen_; + + // Indicates whether |message_loop_runner_| is running. + bool loop_is_running_; + + // Loop that runs while waiting for notification callback. + scoped_refptr<content::MessageLoopRunner> message_loop_runner_; + + // For automatically unsubscribing from callback-based notifications. + SessionRestore::CallbackSubscription callback_subscription_; + + // For safely binding pointers to callbacks. + base::WeakPtrFactory<SessionRestoreTestHelper> weak_ptr_factory; + + DISALLOW_COPY_AND_ASSIGN(SessionRestoreTestHelper); +}; + +#endif // CHROME_BROWSER_SESSIONS_SESSION_RESTORE_TEST_HELPER_H_
diff --git a/chrome/browser/signin/signin_error_notifier_ash.cc b/chrome/browser/signin/signin_error_notifier_ash.cc index a7d663e..e3cb0e9 100644 --- a/chrome/browser/signin/signin_error_notifier_ash.cc +++ b/chrome/browser/signin/signin_error_notifier_ash.cc
@@ -183,7 +183,6 @@ GetMessageBody(), ui::ResourceBundle::GetSharedInstance().GetImageNamed( IDR_NOTIFICATION_ALERT), - blink::WebTextDirectionDefault, notifier_id, base::string16(), // display_source base::ASCIIToUTF16(notification_id_),
diff --git a/chrome/browser/ssl/captive_portal_blocking_page.cc b/chrome/browser/ssl/captive_portal_blocking_page.cc index 97d6f88c..216e6ba 100644 --- a/chrome/browser/ssl/captive_portal_blocking_page.cc +++ b/chrome/browser/ssl/captive_portal_blocking_page.cc
@@ -4,16 +4,22 @@ #include "chrome/browser/ssl/captive_portal_blocking_page.h" +#include "base/i18n/rtl.h" #include "base/metrics/histogram.h" +#include "base/prefs/pref_service.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" +#include "chrome/browser/captive_portal/captive_portal_tab_helper.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/common/pref_names.h" +#include "components/captive_portal/captive_portal_detector.h" #include "content/public/browser/web_contents.h" #include "grit/generated_resources.h" +#include "net/base/net_util.h" #include "ui/base/l10n/l10n_util.h" -#if defined(ENABLE_CAPTIVE_PORTAL_DETECTION) -#include "chrome/browser/captive_portal/captive_portal_tab_helper.h" +#if !defined(ENABLE_CAPTIVE_PORTAL_DETECTION) +#error This file must be built with ENABLE_CAPTIVE_PORTAL_DETECTION flag. #endif namespace { @@ -42,12 +48,12 @@ CaptivePortalBlockingPage::CaptivePortalBlockingPage( content::WebContents* web_contents, const GURL& request_url, + const GURL& login_url, const base::Callback<void(bool)>& callback) : SecurityInterstitialPage(web_contents, request_url), + login_url_(login_url), callback_(callback) { -#if !defined(ENABLE_CAPTIVE_PORTAL_DETECTION) - NOTREACHED(); -#endif + DCHECK(login_url_.is_valid()); RecordUMA(SHOW_ALL); } @@ -79,12 +85,33 @@ l10n_util::GetStringUTF16(IDS_CAPTIVE_PORTAL_BUTTON_OPEN_LOGIN_PAGE)); load_time_data->SetString("tabTitle", l10n_util::GetStringUTF16(IDS_CAPTIVE_PORTAL_TITLE)); - load_time_data->SetString( - "primaryParagraph", - l10n_util::GetStringUTF16(IDS_CAPTIVE_PORTAL_PRIMARY_PARAGRAPH)); load_time_data->SetString("heading", l10n_util::GetStringUTF16(IDS_CAPTIVE_PORTAL_HEADING)); + if (login_url_.spec() == captive_portal::CaptivePortalDetector::kDefaultURL) { + // Captive portal may intercept requests without HTTP redirects, in which + // case the login url would be the same as the captive portal detection url. + // Don't show the login url in that case. + load_time_data->SetString( + "primaryParagraph", + l10n_util::GetStringUTF16( + IDS_CAPTIVE_PORTAL_PRIMARY_PARAGRAPH_NO_LOGIN_URL)); + } else { + std::string languages; + Profile* profile = Profile::FromBrowserContext( + web_contents()->GetBrowserContext()); + if (profile) + languages = profile->GetPrefs()->GetString(prefs::kAcceptLanguages); + + base::string16 login_host = net::IDNToUnicode(login_url_.host(), languages); + if (base::i18n::IsRTL()) + base::i18n::WrapStringWithLTRFormatting(&login_host); + load_time_data->SetString( + "primaryParagraph", + l10n_util::GetStringFUTF16(IDS_CAPTIVE_PORTAL_PRIMARY_PARAGRAPH, + login_host)); + } + // Fill the empty strings to avoid getting debug warnings. load_time_data->SetString("openDetails", base::string16()); load_time_data->SetString("closeDetails", base::string16()); @@ -96,8 +123,6 @@ // The response has quotes around it. if (command == std::string("\"") + kOpenLoginPageCommand + "\"") { RecordUMA(OPEN_LOGIN_PAGE); -#if defined(ENABLE_CAPTIVE_PORTAL_DETECTION) CaptivePortalTabHelper::OpenLoginTabForWebContents(web_contents(), true); -#endif } }
diff --git a/chrome/browser/ssl/captive_portal_blocking_page.h b/chrome/browser/ssl/captive_portal_blocking_page.h index 7e5b7ae..18a4bab 100644 --- a/chrome/browser/ssl/captive_portal_blocking_page.h +++ b/chrome/browser/ssl/captive_portal_blocking_page.h
@@ -10,8 +10,7 @@ #include "base/callback.h" #include "base/macros.h" #include "chrome/browser/interstitials/security_interstitial_page.h" - -class GURL; +#include "url/gurl.h" namespace content{ class WebContents; @@ -31,6 +30,7 @@ CaptivePortalBlockingPage(content::WebContents* web_contents, const GURL& request_url, + const GURL& login_url, const base::Callback<void(bool)>& callback); ~CaptivePortalBlockingPage() override; @@ -47,6 +47,8 @@ void CommandReceived(const std::string& command) override; private: + // URL of the login page, opened when the user clicks the "Connect" button. + GURL login_url_; base::Callback<void(bool)> callback_; DISALLOW_COPY_AND_ASSIGN(CaptivePortalBlockingPage);
diff --git a/chrome/browser/ssl/captive_portal_blocking_page_browsertest.cc b/chrome/browser/ssl/captive_portal_blocking_page_browsertest.cc new file mode 100644 index 0000000..a5d3483 --- /dev/null +++ b/chrome/browser/ssl/captive_portal_blocking_page_browsertest.cc
@@ -0,0 +1,143 @@ +// Copyright 2015 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/ssl/captive_portal_blocking_page.h" + +#include <string> + +#include "base/callback.h" +#include "base/logging.h" +#include "base/macros.h" +#include "base/prefs/pref_service.h" +#include "base/strings/stringprintf.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/common/pref_names.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "components/captive_portal/captive_portal_detector.h" +#include "content/public/browser/interstitial_page.h" +#include "content/public/browser/web_contents.h" +#include "content/public/test/browser_test_utils.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" + +// Partial text in the captive portal interstitial's main paragraph when the +// login domain isn't displayed. +const char kGenericLoginURLText[] = "its login page"; +const char kBrokenSSL[] = "https://broken.ssl"; + +// Returns true if the interstitial contains |text| in its body. +bool IsInterstitialDisplayingText(content::InterstitialPage* interstitial, + const std::string& text) { + // It's valid for |text| to contain "\'", but simply look for "'" instead + // since this function is used for searching host names and a predefined + // string. + DCHECK(text.find("\'") == std::string::npos); + std::string command = base::StringPrintf( + "var hasText = document.body.textContent.indexOf('%s') >= 0;" + "window.domAutomationController.send(hasText);", + text.c_str()); + bool result = false; + EXPECT_TRUE(content::ExecuteScriptAndExtractBool( + interstitial->GetMainFrame(), command, &result)); + return result; +} + +class CaptivePortalBlockingPageTest : public InProcessBrowserTest { + public: + CaptivePortalBlockingPageTest() {} + + private: + DISALLOW_COPY_AND_ASSIGN(CaptivePortalBlockingPageTest); +}; + +// The captive portal interstitial should show the login url if the login url +// is different than the captive portal ping url (i.e. the portal intercepts +// requests via HTTP redirects). +IN_PROC_BROWSER_TEST_F(CaptivePortalBlockingPageTest, + ShowLoginDomainIfPortalRedirectsDetectionURL) { + const GURL kLandingUrl("http://captive.portal/landing_url"); + content::WebContents* contents = + browser()->tab_strip_model()->GetActiveWebContents(); + DCHECK(contents); + // Blocking page is owned by the interstitial. + CaptivePortalBlockingPage* blocking_page = new CaptivePortalBlockingPage( + contents, GURL(kBrokenSSL), kLandingUrl, base::Callback<void(bool)>()); + blocking_page->Show(); + + WaitForInterstitialAttach(contents); + EXPECT_TRUE( + WaitForRenderFrameReady(contents->GetInterstitialPage()->GetMainFrame())); + + EXPECT_TRUE(IsInterstitialDisplayingText(contents->GetInterstitialPage(), + kLandingUrl.host())); + EXPECT_FALSE(IsInterstitialDisplayingText(contents->GetInterstitialPage(), + kGenericLoginURLText)); +} + +// The captive portal interstitial should show a generic text if the login url +// is the same as the captive portal ping url (i.e. the portal intercepts +// requests without using HTTP redirects). +IN_PROC_BROWSER_TEST_F(CaptivePortalBlockingPageTest, + DontShowLoginDomainIfPortalDoesntRedirectDetectionURL) { + const GURL kLandingUrl(captive_portal::CaptivePortalDetector::kDefaultURL); + content::WebContents* contents = + browser()->tab_strip_model()->GetActiveWebContents(); + DCHECK(contents); + // Blocking page is owned by the interstitial. + CaptivePortalBlockingPage* blocking_page = new CaptivePortalBlockingPage( + contents, GURL(kBrokenSSL), kLandingUrl, base::Callback<void(bool)>()); + blocking_page->Show(); + + WaitForInterstitialAttach(contents); + EXPECT_TRUE( + WaitForRenderFrameReady(contents->GetInterstitialPage()->GetMainFrame())); + + EXPECT_FALSE(IsInterstitialDisplayingText(contents->GetInterstitialPage(), + kLandingUrl.host())); + EXPECT_TRUE(IsInterstitialDisplayingText(contents->GetInterstitialPage(), + kGenericLoginURLText)); +} + +class CaptivePortalBlockingPageIDNTest : public InProcessBrowserTest { +public: + // InProcessBrowserTest: + void SetUpOnMainThread() override { + // Clear AcceptLanguages to force punycode decoding. + browser()->profile()->GetPrefs()->SetString(prefs::kAcceptLanguages, + std::string()); + } +}; + +// Same as ShowLoginDomainIfPortalRedirectsDetectionURL, except the login +// domain is an IDN. +IN_PROC_BROWSER_TEST_F(CaptivePortalBlockingPageIDNTest, + ShowLoginIDNIfPortalRedirectsDetectionURL) { + const char kHostname[] = + "xn--d1abbgf6aiiy.xn--p1ai"; + const char kHostnameJSUnicode[] = + "\\u043f\\u0440\\u0435\\u0437\\u0438\\u0434\\u0435\\u043d\\u0442." + "\\u0440\\u0444"; + std::string landing_url_spec = + base::StringPrintf("http://%s/landing_url", kHostname); + GURL landing_url(landing_url_spec); + + content::WebContents* contents = + browser()->tab_strip_model()->GetActiveWebContents(); + DCHECK(contents); + // Blocking page is owned by the interstitial. + CaptivePortalBlockingPage* blocking_page = new CaptivePortalBlockingPage( + contents, GURL(kBrokenSSL), landing_url, base::Callback<void(bool)>()); + blocking_page->Show(); + + WaitForInterstitialAttach(contents); + EXPECT_TRUE( + WaitForRenderFrameReady(contents->GetInterstitialPage()->GetMainFrame())); + + EXPECT_TRUE(IsInterstitialDisplayingText(contents->GetInterstitialPage(), + kHostnameJSUnicode)); + EXPECT_FALSE(IsInterstitialDisplayingText(contents->GetInterstitialPage(), + kGenericLoginURLText)); +}
diff --git a/chrome/browser/ssl/ssl_error_handler.cc b/chrome/browser/ssl/ssl_error_handler.cc index 708162f..041f8f6 100644 --- a/chrome/browser/ssl/ssl_error_handler.cc +++ b/chrome/browser/ssl/ssl_error_handler.cc
@@ -178,13 +178,13 @@ #endif } -void SSLErrorHandler::ShowCaptivePortalInterstitial() { +void SSLErrorHandler::ShowCaptivePortalInterstitial(const GURL& landing_url) { #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION) // Show captive portal blocking page. The interstitial owns the blocking page. RecordUMA(SSLBlockingPage::IsOptionsOverridable(options_mask_) ? SHOW_CAPTIVE_PORTAL_INTERSTITIAL_OVERRIDABLE : SHOW_CAPTIVE_PORTAL_INTERSTITIAL_NONOVERRIDABLE); - (new CaptivePortalBlockingPage(web_contents_, request_url_, + (new CaptivePortalBlockingPage(web_contents_, request_url_, landing_url, callback_))->Show(); // Once an interstitial is displayed, no need to keep the handler around. // This is the equivalent of "delete this". @@ -216,7 +216,7 @@ CaptivePortalService::Results* results = content::Details<CaptivePortalService::Results>(details).ptr(); if (results->result == captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL) - ShowCaptivePortalInterstitial(); + ShowCaptivePortalInterstitial(results->landing_url); else ShowSSLInterstitial(); }
diff --git a/chrome/browser/ssl/ssl_error_handler.h b/chrome/browser/ssl/ssl_error_handler.h index 0a964320..fb6fd70 100644 --- a/chrome/browser/ssl/ssl_error_handler.h +++ b/chrome/browser/ssl/ssl_error_handler.h
@@ -82,7 +82,7 @@ // These are virtual for tests: virtual void CheckForCaptivePortal(); - virtual void ShowCaptivePortalInterstitial(); + virtual void ShowCaptivePortalInterstitial(const GURL& landing_url); virtual void ShowSSLInterstitial(); // content::NotificationObserver:
diff --git a/chrome/browser/ssl/ssl_error_handler_unittest.cc b/chrome/browser/ssl/ssl_error_handler_unittest.cc index 8efad4b..96ef738c 100644 --- a/chrome/browser/ssl/ssl_error_handler_unittest.cc +++ b/chrome/browser/ssl/ssl_error_handler_unittest.cc
@@ -83,7 +83,7 @@ ssl_interstitial_shown_ = true; } - void ShowCaptivePortalInterstitial() override { + void ShowCaptivePortalInterstitial(const GURL& landing_url) override { captive_portal_interstitial_shown_ = true; }
diff --git a/chrome/browser/supervised_user/child_accounts/child_account_service.cc b/chrome/browser/supervised_user/child_accounts/child_account_service.cc index a0c30ac..25eb5ce9 100644 --- a/chrome/browser/supervised_user/child_accounts/child_account_service.cc +++ b/chrome/browser/supervised_user/child_accounts/child_account_service.cc
@@ -36,11 +36,12 @@ const char kIsChildAccountServiceFlagName[] = "uca"; -// Normally, re-check the child account flag once per day. -const int kStatusFlagUpdateIntervalSeconds = 60 * 60 * 24; +// Normally, re-check the child account flag and the family info once per day. +const int kUpdateIntervalSeconds = 60 * 60 * 24; -// In case of an error while getting the flag, retry with exponential backoff. -const net::BackoffEntry::Policy kFlagFetchBackoffPolicy = { +// In case of an error while getting the flag or the family info, retry with +// exponential backoff. +const net::BackoffEntry::Policy kBackoffPolicy = { // Number of initial errors (in sequence) to ignore before applying // exponential back-off rules. 0, @@ -68,12 +69,14 @@ ChildAccountService::ChildAccountService(Profile* profile) : profile_(profile), active_(false), - flag_fetch_backoff_(&kFlagFetchBackoffPolicy), + flag_fetch_backoff_(&kBackoffPolicy), + family_fetch_backoff_(&kBackoffPolicy), weak_ptr_factory_(this) {} ChildAccountService::~ChildAccountService() {} void ChildAccountService::SetIsChildAccount(bool is_child_account) { + PropagateChildStatusToUser(is_child_account); if (profile_->IsChild() == is_child_account) return; @@ -83,7 +86,6 @@ } else { profile_->GetPrefs()->ClearPref(prefs::kSupervisedUserId); } - PropagateChildStatusToUser(is_child_account); } void ChildAccountService::Init() { @@ -128,16 +130,9 @@ SigninManagerFactory::GetForProfile(profile_)->ProhibitSignout(true); #endif - // TODO(treib): Maybe only fetch the parents on the first start, and then - // refresh occasionally (like once every 24h)? That's what - // GAIAInfoUpdateService does. - family_fetcher_.reset(new FamilyInfoFetcher( - this, - SigninManagerFactory::GetForProfile(profile_) - ->GetAuthenticatedAccountId(), - ProfileOAuth2TokenServiceFactory::GetForProfile(profile_), - profile_->GetRequestContext())); - family_fetcher_->StartGetFamilyMembers(); + // TODO(treib): Maybe store the last update time in a pref, so we don't + // have to re-fetch on every start. + StartFetchingFamilyInfo(); SupervisedUserService* service = SupervisedUserServiceFactory::GetForProfile(profile_); @@ -205,6 +200,7 @@ const std::string& username) { DCHECK(!profile_->IsChild()); CancelFetchingServiceFlags(); + CancelFetchingFamilyInfo(); } void ChildAccountService::OnGetFamilyMembersSuccess( @@ -229,12 +225,37 @@ if (!parent_found) ClearSecondCustodianPrefs(); family_fetcher_.reset(); + + family_fetch_backoff_.InformOfRequest(true); + + ScheduleNextFamilyInfoUpdate( + base::TimeDelta::FromSeconds(kUpdateIntervalSeconds)); } void ChildAccountService::OnFailure(FamilyInfoFetcher::ErrorCode error) { DLOG(WARNING) << "GetFamilyMembers failed with code " << error; + family_fetch_backoff_.InformOfRequest(false); + ScheduleNextFamilyInfoUpdate(family_fetch_backoff_.GetTimeUntilRelease()); +} + +void ChildAccountService::StartFetchingFamilyInfo() { + family_fetcher_.reset(new FamilyInfoFetcher( + this, + SigninManagerFactory::GetForProfile(profile_) + ->GetAuthenticatedAccountId(), + ProfileOAuth2TokenServiceFactory::GetForProfile(profile_), + profile_->GetRequestContext())); + family_fetcher_->StartGetFamilyMembers(); +} + +void ChildAccountService::CancelFetchingFamilyInfo() { family_fetcher_.reset(); - // TODO(treib): Retry after a while? + family_fetch_timer_.Stop(); +} + +void ChildAccountService::ScheduleNextFamilyInfoUpdate(base::TimeDelta delay) { + family_fetch_timer_.Start( + FROM_HERE, delay, this, &ChildAccountService::StartFetchingFamilyInfo); } void ChildAccountService::StartFetchingServiceFlags() { @@ -282,8 +303,8 @@ kIsChildAccountServiceFlagName) != flags.end(); SetIsChildAccount(is_child_account); - ScheduleNextStatusFlagUpdate(base::TimeDelta::FromSeconds( - kStatusFlagUpdateIntervalSeconds)); + ScheduleNextStatusFlagUpdate( + base::TimeDelta::FromSeconds(kUpdateIntervalSeconds)); } void ChildAccountService::ScheduleNextStatusFlagUpdate(base::TimeDelta delay) {
diff --git a/chrome/browser/supervised_user/child_accounts/child_account_service.h b/chrome/browser/supervised_user/child_accounts/child_account_service.h index 0c2fb1c..4a151967 100644 --- a/chrome/browser/supervised_user/child_accounts/child_account_service.h +++ b/chrome/browser/supervised_user/child_accounts/child_account_service.h
@@ -70,6 +70,10 @@ const std::vector<FamilyInfoFetcher::FamilyMember>& members) override; void OnFailure(FamilyInfoFetcher::ErrorCode error) override; + void StartFetchingFamilyInfo(); + void CancelFetchingFamilyInfo(); + void ScheduleNextFamilyInfoUpdate(base::TimeDelta delay); + void StartFetchingServiceFlags(); void CancelFetchingServiceFlags(); void OnFlagsFetched(AccountServiceFlagFetcher::ResultCode, @@ -101,6 +105,9 @@ net::BackoffEntry flag_fetch_backoff_; scoped_ptr<FamilyInfoFetcher> family_fetcher_; + // If fetching the family info fails, retry with exponential backoff. + base::OneShotTimer<ChildAccountService> family_fetch_timer_; + net::BackoffEntry family_fetch_backoff_; base::WeakPtrFactory<ChildAccountService> weak_ptr_factory_;
diff --git a/chrome/browser/supervised_user/supervised_user_interstitial.cc b/chrome/browser/supervised_user/supervised_user_interstitial.cc index 5572eba..96d022d 100644 --- a/chrome/browser/supervised_user/supervised_user_interstitial.cc +++ b/chrome/browser/supervised_user/supervised_user_interstitial.cc
@@ -269,8 +269,11 @@ webui::SetFontAndTextDirection(&strings); - base::StringPiece html(ResourceBundle::GetSharedInstance().GetRawDataResource( - IDR_SUPERVISED_USER_BLOCK_INTERSTITIAL_HTML)); + std::string html = + ResourceBundle::GetSharedInstance() + .GetRawDataResource(IDR_SUPERVISED_USER_BLOCK_INTERSTITIAL_HTML) + .as_string(); + webui::AppendWebUiCssTextDefaults(&html); return webui::GetI18nTemplateHtml(html, &strings); }
diff --git a/chrome/browser/sync/sync_error_notifier_ash.cc b/chrome/browser/sync/sync_error_notifier_ash.cc index 4af01aa..41b1b7b 100644 --- a/chrome/browser/sync/sync_error_notifier_ash.cc +++ b/chrome/browser/sync/sync_error_notifier_ash.cc
@@ -175,7 +175,6 @@ l10n_util::GetStringUTF16(IDS_SYNC_PASSPHRASE_ERROR_BUBBLE_VIEW_MESSAGE), ui::ResourceBundle::GetSharedInstance().GetImageNamed( IDR_NOTIFICATION_ALERT), - blink::WebTextDirectionDefault, notifier_id, base::string16(), // display_source base::ASCIIToUTF16(notification_id_),
diff --git a/chrome/browser/sync/test/integration/two_client_apps_sync_test.cc b/chrome/browser/sync/test/integration/two_client_apps_sync_test.cc index 58d590a..cbdac9c0 100644 --- a/chrome/browser/sync/test/integration/two_client_apps_sync_test.cc +++ b/chrome/browser/sync/test/integration/two_client_apps_sync_test.cc
@@ -366,21 +366,17 @@ ASSERT_TRUE(AllProfilesHaveSameAppsAsVerifier()); // Change the launch type to window. - extensions::SetLaunchType(GetExtensionService(GetProfile(1)), - extensions::kWebStoreAppId, + extensions::SetLaunchType(GetProfile(1), extensions::kWebStoreAppId, extensions::LAUNCH_TYPE_WINDOW); - extensions::SetLaunchType(GetExtensionService(verifier()), - extensions::kWebStoreAppId, + extensions::SetLaunchType(verifier(), extensions::kWebStoreAppId, extensions::LAUNCH_TYPE_WINDOW); ASSERT_TRUE(AwaitAllProfilesHaveSameAppsAsVerifier()); // Change the launch type to regular tab. - extensions::SetLaunchType(GetExtensionService(GetProfile(1)), - extensions::kWebStoreAppId, + extensions::SetLaunchType(GetProfile(1), extensions::kWebStoreAppId, extensions::LAUNCH_TYPE_REGULAR); ASSERT_FALSE(HasSameAppsAsVerifier(1)); - extensions::SetLaunchType(GetExtensionService(verifier()), - extensions::kWebStoreAppId, + extensions::SetLaunchType(verifier(), extensions::kWebStoreAppId, extensions::LAUNCH_TYPE_REGULAR); ASSERT_TRUE(AwaitAllProfilesHaveSameAppsAsVerifier()); } @@ -389,11 +385,9 @@ ASSERT_TRUE(SetupSync()); ASSERT_TRUE(AllProfilesHaveSameAppsAsVerifier()); - extensions::SetLaunchType(GetExtensionService(GetProfile(1)), - extensions::kWebStoreAppId, + extensions::SetLaunchType(GetProfile(1), extensions::kWebStoreAppId, extensions::LAUNCH_TYPE_REGULAR); - extensions::SetLaunchType(GetExtensionService(verifier()), - extensions::kWebStoreAppId, + extensions::SetLaunchType(verifier(), extensions::kWebStoreAppId, extensions::LAUNCH_TYPE_REGULAR); ASSERT_TRUE(AwaitAllProfilesHaveSameAppsAsVerifier());
diff --git a/chrome/browser/sync_file_system/drive_backend/drive_backend_util.h b/chrome/browser/sync_file_system/drive_backend/drive_backend_util.h index 6bf5f63..6b17e50 100644 --- a/chrome/browser/sync_file_system/drive_backend/drive_backend_util.h +++ b/chrome/browser/sync_file_system/drive_backend/drive_backend_util.h
@@ -14,7 +14,7 @@ #include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h" #include "chrome/browser/sync_file_system/sync_status_code.h" #include "google_apis/drive/gdata_errorcode.h" -#include "storage/common/blob/scoped_file.h" +#include "storage/browser/blob/scoped_file.h" namespace google_apis { class ChangeResource;
diff --git a/chrome/browser/sync_file_system/drive_backend/folder_creator.cc b/chrome/browser/sync_file_system/drive_backend/folder_creator.cc index 541f3aa0..4e72cf7 100644 --- a/chrome/browser/sync_file_system/drive_backend/folder_creator.cc +++ b/chrome/browser/sync_file_system/drive_backend/folder_creator.cc
@@ -18,7 +18,6 @@ namespace google_apis { class ResourceEntry; -class ResourceList; } namespace sync_file_system {
diff --git a/chrome/browser/sync_file_system/drive_backend/local_to_remote_syncer.h b/chrome/browser/sync_file_system/drive_backend/local_to_remote_syncer.h index a46bf6d2..9d24053 100644 --- a/chrome/browser/sync_file_system/drive_backend/local_to_remote_syncer.h +++ b/chrome/browser/sync_file_system/drive_backend/local_to_remote_syncer.h
@@ -23,7 +23,6 @@ namespace google_apis { class FileResource; -class ResourceList; } namespace sync_file_system {
diff --git a/chrome/browser/sync_file_system/drive_backend/register_app_task.h b/chrome/browser/sync_file_system/drive_backend/register_app_task.h index 2bd628ea..1c279c5 100644 --- a/chrome/browser/sync_file_system/drive_backend/register_app_task.h +++ b/chrome/browser/sync_file_system/drive_backend/register_app_task.h
@@ -19,7 +19,6 @@ namespace google_apis { class ResourceEntry; -class ResourceList; } namespace sync_file_system {
diff --git a/chrome/browser/sync_file_system/drive_backend/sync_engine.cc b/chrome/browser/sync_file_system/drive_backend/sync_engine.cc index c0b2fea..af03581 100644 --- a/chrome/browser/sync_file_system/drive_backend/sync_engine.cc +++ b/chrome/browser/sync_file_system/drive_backend/sync_engine.cc
@@ -52,9 +52,8 @@ #include "extensions/browser/extensions_browser_client.h" #include "extensions/common/extension.h" #include "google_apis/drive/drive_api_url_generator.h" -#include "google_apis/drive/gdata_wapi_url_generator.h" #include "net/url_request/url_request_context_getter.h" -#include "storage/common/blob/scoped_file.h" +#include "storage/browser/blob/scoped_file.h" #include "storage/common/fileapi/file_system_util.h" namespace sync_file_system { @@ -76,7 +75,6 @@ GURL(google_apis::DriveApiUrlGenerator::kBaseUrlForProduction), GURL(google_apis::DriveApiUrlGenerator:: kBaseDownloadUrlForProduction), - GURL(google_apis::GDataWapiUrlGenerator::kBaseUrlForProduction), std::string() /* custom_user_agent */)); }
diff --git a/chrome/browser/sync_file_system/drive_backend/sync_engine_initializer.cc b/chrome/browser/sync_file_system/drive_backend/sync_engine_initializer.cc index 597ce10..9684e00 100644 --- a/chrome/browser/sync_file_system/drive_backend/sync_engine_initializer.cc +++ b/chrome/browser/sync_file_system/drive_backend/sync_engine_initializer.cc
@@ -44,11 +44,6 @@ return left.created_date() < right.created_date(); } -typedef base::Callback<void(scoped_ptr<SyncTaskToken> token, - google_apis::GDataErrorCode error, - scoped_ptr<google_apis::ResourceList> resources)> - TokenAndResourceListCallback; - // Functions above are for wrapping the access to legacy GData WAPI classes. ////////////////////////////////////////////////////////////////////////////////
diff --git a/chrome/browser/sync_file_system/drive_backend/uninstall_app_task.h b/chrome/browser/sync_file_system/drive_backend/uninstall_app_task.h index e6baead3..8784ac7b 100644 --- a/chrome/browser/sync_file_system/drive_backend/uninstall_app_task.h +++ b/chrome/browser/sync_file_system/drive_backend/uninstall_app_task.h
@@ -20,7 +20,6 @@ namespace google_apis { class ResourceEntry; -class ResourceList; } namespace sync_file_system {
diff --git a/chrome/browser/sync_file_system/local/canned_syncable_file_system.cc b/chrome/browser/sync_file_system/local/canned_syncable_file_system.cc index c636e35..2e6f1fc 100644 --- a/chrome/browser/sync_file_system/local/canned_syncable_file_system.cc +++ b/chrome/browser/sync_file_system/local/canned_syncable_file_system.cc
@@ -24,13 +24,13 @@ #include "content/public/test/mock_blob_url_request_context.h" #include "content/public/test/mock_special_storage_policy.h" #include "content/public/test/test_file_system_options.h" +#include "storage/browser/blob/shareable_file_reference.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" #include "storage/browser/fileapi/file_system_operation_context.h" #include "storage/browser/fileapi/file_system_operation_runner.h" #include "storage/browser/quota/quota_manager.h" -#include "storage/common/blob/shareable_file_reference.h" #include "testing/gtest/include/gtest/gtest.h" using base::File;
diff --git a/chrome/browser/sync_file_system/local/local_file_sync_context.cc b/chrome/browser/sync_file_system/local/local_file_sync_context.cc index 88273ab..0aafc6d 100644 --- a/chrome/browser/sync_file_system/local/local_file_sync_context.cc +++ b/chrome/browser/sync_file_system/local/local_file_sync_context.cc
@@ -19,11 +19,11 @@ #include "chrome/browser/sync_file_system/logger.h" #include "chrome/browser/sync_file_system/sync_file_metadata.h" #include "chrome/browser/sync_file_system/syncable_file_system_util.h" +#include "storage/browser/blob/scoped_file.h" #include "storage/browser/fileapi/file_system_context.h" #include "storage/browser/fileapi/file_system_file_util.h" #include "storage/browser/fileapi/file_system_operation_context.h" #include "storage/browser/fileapi/file_system_operation_runner.h" -#include "storage/common/blob/scoped_file.h" #include "storage/common/fileapi/file_system_util.h" using storage::FileSystemContext;
diff --git a/chrome/browser/sync_file_system/local/local_file_sync_context_unittest.cc b/chrome/browser/sync_file_system/local/local_file_sync_context_unittest.cc index e74826f..c2e2388 100644 --- a/chrome/browser/sync_file_system/local/local_file_sync_context_unittest.cc +++ b/chrome/browser/sync_file_system/local/local_file_sync_context_unittest.cc
@@ -21,10 +21,10 @@ #include "content/public/browser/browser_thread.h" #include "content/public/test/mock_blob_url_request_context.h" #include "content/public/test/test_browser_thread_bundle.h" +#include "storage/browser/blob/scoped_file.h" #include "storage/browser/fileapi/file_system_context.h" #include "storage/browser/fileapi/file_system_operation_runner.h" #include "storage/browser/fileapi/isolated_context.h" -#include "storage/common/blob/scoped_file.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/leveldatabase/src/helpers/memenv/memenv.h" #include "third_party/leveldatabase/src/include/leveldb/env.h"
diff --git a/chrome/browser/sync_file_system/local/local_file_sync_service.cc b/chrome/browser/sync_file_system/local/local_file_sync_service.cc index cb4f0f2..51ab55a 100644 --- a/chrome/browser/sync_file_system/local/local_file_sync_service.cc +++ b/chrome/browser/sync_file_system/local/local_file_sync_service.cc
@@ -22,9 +22,9 @@ #include "content/public/browser/storage_partition.h" #include "extensions/browser/extension_registry.h" #include "extensions/common/extension_set.h" +#include "storage/browser/blob/scoped_file.h" #include "storage/browser/fileapi/file_system_context.h" #include "storage/browser/fileapi/file_system_url.h" -#include "storage/common/blob/scoped_file.h" #include "url/gurl.h" using content::BrowserThread;
diff --git a/chrome/browser/sync_file_system/local/syncable_file_system_operation.cc b/chrome/browser/sync_file_system/local/syncable_file_system_operation.cc index 5a2e7b57..d751a56 100644 --- a/chrome/browser/sync_file_system/local/syncable_file_system_operation.cc +++ b/chrome/browser/sync_file_system/local/syncable_file_system_operation.cc
@@ -10,12 +10,12 @@ #include "chrome/browser/sync_file_system/local/syncable_file_operation_runner.h" #include "chrome/browser/sync_file_system/syncable_file_system_util.h" #include "net/url_request/url_request.h" +#include "storage/browser/blob/shareable_file_reference.h" #include "storage/browser/fileapi/file_system_context.h" #include "storage/browser/fileapi/file_system_operation.h" #include "storage/browser/fileapi/file_system_operation_context.h" #include "storage/browser/fileapi/file_system_url.h" #include "storage/browser/fileapi/file_writer_delegate.h" -#include "storage/common/blob/shareable_file_reference.h" using storage::FileSystemURL;
diff --git a/chrome/browser/test_presubmit.py b/chrome/browser/test_presubmit.py index b112eac..d37a6b3e 100755 --- a/chrome/browser/test_presubmit.py +++ b/chrome/browser/test_presubmit.py
@@ -18,7 +18,8 @@ import find_depot_tools # pylint: disable=W0611 from testing_support.super_mox import SuperMoxTestBase -from web_dev_style import resource_checker, css_checker, js_checker # pylint: disable=F0401 +from web_dev_style import css_checker, html_checker, js_checker, \ + resource_checker # pylint: disable=F0401 def GetHighlight(line, error): @@ -28,6 +29,47 @@ return ''.join(ch1 for (ch1, ch2) in zip(line, highlight) if ch2 == '^') +class HtmlStyleTest(SuperMoxTestBase): + def setUp(self): + SuperMoxTestBase.setUp(self) + + input_api = self.mox.CreateMockAnything() + input_api.re = re + output_api = self.mox.CreateMockAnything() + self.checker = html_checker.HtmlChecker(input_api, output_api) + + def ShouldFailLabelCheck(self, line): + """Checks that the label checker flags |line| as a style error.""" + error = self.checker.LabelCheck(1, line) + self.assertNotEqual('', error, 'Should be flagged as style error: ' + line) + highlight = GetHighlight(line, error).strip() + self.assertEqual('for=', highlight) + + def ShouldPassLabelCheck(self, line): + """Checks that the label checker doesn't flag |line| as a style error.""" + error = self.checker.LabelCheck(1, line) + self.assertEqual('', error, 'Should not be flagged as style error: ' + line) + + def testForAttributeFails(self): + lines = [ + " for=\"abc\"", + "for= ", + " \tfor= ", + " for=" + ] + for line in lines: + self.ShouldFailLabelCheck(line) + + def testOtherAttributesPass(self): + lines = [ + " my-for=\"abc\" ", + " myfor=\"abc\" ", + " <for", + ] + for line in lines: + self.ShouldPassLabelCheck(line) + + class ResourceStyleGuideTest(SuperMoxTestBase): def setUp(self): SuperMoxTestBase.setUp(self)
diff --git a/chrome/browser/ui/android/autofill/card_unmask_prompt_view_android.cc b/chrome/browser/ui/android/autofill/card_unmask_prompt_view_android.cc index f286813..7a97476 100644 --- a/chrome/browser/ui/android/autofill/card_unmask_prompt_view_android.cc +++ b/chrome/browser/ui/android/autofill/card_unmask_prompt_view_android.cc
@@ -60,7 +60,9 @@ jobject obj, jstring response) { controller_->OnUnmaskResponse( - base::android::ConvertJavaStringToUTF16(env, response)); + base::android::ConvertJavaStringToUTF16(env, response), + base::string16(), + base::string16()); } void CardUnmaskPromptViewAndroid::PromptDismissed(JNIEnv* env, jobject obj) {
diff --git a/chrome/browser/ui/android/javascript_app_modal_dialog_android.cc b/chrome/browser/ui/android/javascript_app_modal_dialog_android.cc index ff38705..1aabefa 100644 --- a/chrome/browser/ui/android/javascript_app_modal_dialog_android.cc +++ b/chrome/browser/ui/android/javascript_app_modal_dialog_android.cc
@@ -12,6 +12,8 @@ #include "components/app_modal/javascript_dialog_manager.h" #include "components/app_modal/javascript_native_dialog_factory.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/web_contents.h" +#include "content/public/browser/web_contents_delegate.h" #include "content/public/common/javascript_message_type.h" #include "jni/JavascriptAppModalDialog_jni.h" #include "ui/base/android/window_android.h" @@ -171,11 +173,12 @@ private: app_modal::NativeAppModalDialog* CreateNativeJavaScriptDialog( - app_modal::JavaScriptAppModalDialog* dialog, - gfx::NativeWindow parent_window) override { + app_modal::JavaScriptAppModalDialog* dialog) override { + dialog->web_contents()->GetDelegate()->ActivateContents( + dialog->web_contents()); return new JavascriptAppModalDialogAndroid( base::android::AttachCurrentThread(), - dialog, parent_window); + dialog, dialog->web_contents()->GetTopLevelNativeWindow()); } DISALLOW_COPY_AND_ASSIGN(ChromeJavaScriptNativeDialogAndroidFactory);
diff --git a/chrome/browser/ui/app_list/app_list_controller_delegate.cc b/chrome/browser/ui/app_list/app_list_controller_delegate.cc index 318ec8a..e93132b8 100644 --- a/chrome/browser/ui/app_list/app_list_controller_delegate.cc +++ b/chrome/browser/ui/app_list/app_list_controller_delegate.cc
@@ -188,10 +188,7 @@ Profile* profile, const std::string& extension_id, extensions::LaunchType launch_type) { - ExtensionService* service = - extensions::ExtensionSystem::Get(profile)->extension_service(); - extensions::SetLaunchType( - service, extension_id, launch_type); + extensions::SetLaunchType(profile, extension_id, launch_type); } bool AppListControllerDelegate::IsExtensionInstalled(
diff --git a/chrome/browser/ui/ash/chrome_screenshot_grabber.cc b/chrome/browser/ui/ash/chrome_screenshot_grabber.cc index 20111d4..a3e9211c 100644 --- a/chrome/browser/ui/ash/chrome_screenshot_grabber.cc +++ b/chrome/browser/ui/ash/chrome_screenshot_grabber.cc
@@ -420,7 +420,6 @@ GetScreenshotNotificationText(screenshot_result)), ui::ResourceBundle::GetSharedInstance().GetImageNamed( IDR_SCREENSHOT_NOTIFICATION_ICON), - blink::WebTextDirectionDefault, message_center::NotifierId(message_center::NotifierId::SYSTEM_COMPONENT, ash::system_notifier::kNotifierScreenshot), l10n_util::GetStringUTF16(IDS_MESSAGE_CENTER_NOTIFIER_SCREENSHOT_NAME),
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc index 2846cb7c..b036635 100644 --- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc +++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc
@@ -883,10 +883,7 @@ if (!controller) return; - extensions::SetLaunchType( - extensions::ExtensionSystem::Get(profile_)->extension_service(), - controller->app_id(), - launch_type); + extensions::SetLaunchType(profile_, controller->app_id(), launch_type); } void ChromeLauncherController::UnpinAppWithID(const std::string& app_id) {
diff --git a/chrome/browser/ui/autofill/card_unmask_prompt_controller.h b/chrome/browser/ui/autofill/card_unmask_prompt_controller.h index b4eba4e..85ef4a3 100644 --- a/chrome/browser/ui/autofill/card_unmask_prompt_controller.h +++ b/chrome/browser/ui/autofill/card_unmask_prompt_controller.h
@@ -17,13 +17,16 @@ public: // Interaction. virtual void OnUnmaskDialogClosed() = 0; - virtual void OnUnmaskResponse(const base::string16& cvc) = 0; + virtual void OnUnmaskResponse(const base::string16& cvc, + const base::string16& exp_month, + const base::string16& exp_year) = 0; // State. virtual content::WebContents* GetWebContents() = 0; virtual base::string16 GetWindowTitle() const = 0; virtual base::string16 GetInstructionsMessage() const = 0; virtual int GetCvcImageRid() const = 0; + virtual bool ShouldRequestExpirationDate() const = 0; virtual bool InputTextIsValid(const base::string16& input_text) const = 0; };
diff --git a/chrome/browser/ui/autofill/card_unmask_prompt_controller_impl.cc b/chrome/browser/ui/autofill/card_unmask_prompt_controller_impl.cc index 609ecdb6..70818ee4 100644 --- a/chrome/browser/ui/autofill/card_unmask_prompt_controller_impl.cc +++ b/chrome/browser/ui/autofill/card_unmask_prompt_controller_impl.cc
@@ -48,9 +48,11 @@ } void CardUnmaskPromptControllerImpl::OnUnmaskResponse( - const base::string16& cvc) { + const base::string16& cvc, + const base::string16& exp_month, + const base::string16& exp_year) { card_unmask_view_->DisableAndWaitForVerification(); - delegate_->OnUnmaskResponse(cvc); + delegate_->OnUnmaskResponse(cvc, exp_month, exp_year); } content::WebContents* CardUnmaskPromptControllerImpl::GetWebContents() { @@ -58,10 +60,24 @@ } base::string16 CardUnmaskPromptControllerImpl::GetWindowTitle() const { - return base::ASCIIToUTF16("Unlocking ") + card_.TypeAndLastFourDigits(); + // TODO(estade): i18n. + if (ShouldRequestExpirationDate()) { + return base::ASCIIToUTF16("Update and verify your card ") + + card_.TypeAndLastFourDigits(); + } + + return base::ASCIIToUTF16("Verify your card ") + + card_.TypeAndLastFourDigits(); } base::string16 CardUnmaskPromptControllerImpl::GetInstructionsMessage() const { + if (ShouldRequestExpirationDate()) { + return l10n_util::GetStringUTF16( + card_.type() == kAmericanExpressCard + ? IDS_AUTOFILL_CARD_UNMASK_PROMPT_INSTRUCTIONS_EXPIRED_AMEX + : IDS_AUTOFILL_CARD_UNMASK_PROMPT_INSTRUCTIONS_EXPIRED); + } + return l10n_util::GetStringUTF16( card_.type() == kAmericanExpressCard ? IDS_AUTOFILL_CARD_UNMASK_PROMPT_INSTRUCTIONS_AMEX @@ -73,6 +89,10 @@ : IDR_CREDIT_CARD_CVC_HINT; } +bool CardUnmaskPromptControllerImpl::ShouldRequestExpirationDate() const { + return card_.GetServerStatus() == CreditCard::EXPIRED; +} + bool CardUnmaskPromptControllerImpl::InputTextIsValid( const base::string16& input_text) const { base::string16 trimmed_text;
diff --git a/chrome/browser/ui/autofill/card_unmask_prompt_controller_impl.h b/chrome/browser/ui/autofill/card_unmask_prompt_controller_impl.h index 5e308595..c3d4c62 100644 --- a/chrome/browser/ui/autofill/card_unmask_prompt_controller_impl.h +++ b/chrome/browser/ui/autofill/card_unmask_prompt_controller_impl.h
@@ -27,11 +27,15 @@ // CardUnmaskPromptController implementation. void OnUnmaskDialogClosed() override; - void OnUnmaskResponse(const base::string16& cvc) override; + void OnUnmaskResponse(const base::string16& cvc, + const base::string16& exp_month, + const base::string16& exp_year) override; + content::WebContents* GetWebContents() override; base::string16 GetWindowTitle() const override; base::string16 GetInstructionsMessage() const override; int GetCvcImageRid() const override; + bool ShouldRequestExpirationDate() const override; bool InputTextIsValid(const base::string16& input_text) const override; private:
diff --git a/chrome/browser/ui/autofill/chrome_autofill_client.cc b/chrome/browser/ui/autofill/chrome_autofill_client.cc index 47b82198..dbc94d9 100644 --- a/chrome/browser/ui/autofill/chrome_autofill_client.cc +++ b/chrome/browser/ui/autofill/chrome_autofill_client.cc
@@ -10,6 +10,9 @@ #include "chrome/browser/infobars/infobar_service.h" #include "chrome/browser/password_manager/chrome_password_manager_client.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/signin/profile_identity_provider.h" +#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" +#include "chrome/browser/signin/signin_manager_factory.h" #include "chrome/browser/ui/autofill/autofill_dialog_controller.h" #include "chrome/browser/ui/autofill/autofill_popup_controller_impl.h" #include "chrome/browser/ui/autofill/card_unmask_prompt_view.h" @@ -33,6 +36,7 @@ #include "chrome/browser/android/chromium_application.h" #include "chrome/browser/ui/android/autofill/autofill_logger_android.h" #else +#include "chrome/browser/ui/webui/signin/login_ui_service_factory.h" #include "components/ui/zoom/zoom_controller.h" #endif @@ -99,6 +103,23 @@ ->GetPrefs(); } +IdentityProvider* ChromeAutofillClient::GetIdentityProvider() { + if (!identity_provider_) { + Profile* profile = + Profile::FromBrowserContext(web_contents()->GetBrowserContext()); + LoginUIService* login_service = nullptr; +#if !defined(OS_ANDROID) + login_service = LoginUIServiceFactory::GetForProfile(profile); +#endif + identity_provider_.reset(new ProfileIdentityProvider( + SigninManagerFactory::GetForProfile(profile), + ProfileOAuth2TokenServiceFactory::GetForProfile(profile), + login_service)); + } + + return identity_provider_.get(); +} + void ChromeAutofillClient::ShowAutofillSettings() { #if defined(OS_ANDROID) chrome::android::ChromiumApplication::ShowAutofillSettings();
diff --git a/chrome/browser/ui/autofill/chrome_autofill_client.h b/chrome/browser/ui/autofill/chrome_autofill_client.h index 28f1032e..6385f3c 100644 --- a/chrome/browser/ui/autofill/chrome_autofill_client.h +++ b/chrome/browser/ui/autofill/chrome_autofill_client.h
@@ -46,6 +46,7 @@ PersonalDataManager* GetPersonalDataManager() override; scoped_refptr<AutofillWebDataService> GetDatabase() override; PrefService* GetPrefs() override; + IdentityProvider* GetIdentityProvider() override; void HideRequestAutocompleteDialog() override; void ShowAutofillSettings() override; void ShowUnmaskPrompt(const CreditCard& card, @@ -129,6 +130,9 @@ // The last render frame that called requestAutocomplete. content::RenderFrameHost* last_rfh_to_rac_; + // The identity provider, used for Wallet integration. + scoped_ptr<IdentityProvider> identity_provider_; + DISALLOW_COPY_AND_ASSIGN(ChromeAutofillClient); };
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc index 1745f71..76085e9d 100644 --- a/chrome/browser/ui/browser.cc +++ b/chrome/browser/ui/browser.cc
@@ -104,6 +104,7 @@ #include "chrome/browser/ui/chrome_pages.h" #include "chrome/browser/ui/chrome_select_file_policy.h" #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" +#include "chrome/browser/ui/exclusive_access/mouse_lock_controller.h" #include "chrome/browser/ui/fast_unload_controller.h" #include "chrome/browser/ui/find_bar/find_bar.h" #include "chrome/browser/ui/find_bar/find_bar_controller.h" @@ -444,7 +445,7 @@ #endif // defined(OS_WIN) } - fullscreen_controller_.reset(new FullscreenController(this)); + exclusive_access_manager_.reset(new ExclusiveAccessManager(this)); // Must be initialized after window_. // Also: surprise! a modal dialog host is not necessary to host modal dialogs @@ -784,7 +785,8 @@ // Browser, Tab adding/showing functions: void Browser::WindowFullscreenStateChanged() { - fullscreen_controller_->WindowFullscreenStateChanged(); + exclusive_access_manager_->fullscreen_controller() + ->WindowFullscreenStateChanged(); command_controller_->FullscreenStateChanged(); UpdateBookmarkBarState(BOOKMARK_BAR_STATE_CHANGE_TOGGLE_FULLSCREEN); } @@ -793,8 +795,8 @@ // Browser, Assorted browser commands: void Browser::ToggleFullscreenModeWithExtension(const GURL& extension_url) { - fullscreen_controller_-> - ToggleBrowserFullscreenModeWithExtension(extension_url); + exclusive_access_manager_->fullscreen_controller() + ->ToggleBrowserFullscreenModeWithExtension(extension_url); } bool Browser::SupportsWindowFeature(WindowFeature feature) const { @@ -944,7 +946,7 @@ void Browser::TabClosingAt(TabStripModel* tab_strip_model, WebContents* contents, int index) { - fullscreen_controller_->OnTabClosing(contents); + exclusive_access_manager_->OnTabClosing(contents); SessionService* session_service = SessionServiceFactory::GetForProfile(profile_); if (session_service) @@ -980,7 +982,7 @@ } void Browser::TabDeactivated(WebContents* contents) { - fullscreen_controller_->OnTabDeactivated(contents); + exclusive_access_manager_->OnTabDeactivated(contents); search_delegate_->OnTabDeactivated(contents); SearchTabHelper::FromWebContents(contents)->OnTabDeactivated(); @@ -1008,7 +1010,7 @@ // is updated. window_->OnActiveTabChanged(old_contents, new_contents, index, reason); - fullscreen_controller_->OnTabDetachedFromView(old_contents); + exclusive_access_manager_->OnTabDetachedFromView(old_contents); // Discarded tabs always get reloaded. if (tab_strip_model_->IsTabDiscarded(index)) { @@ -1080,7 +1082,7 @@ WebContents* new_contents, int index) { TabDetachedAtImpl(old_contents, index, DETACH_TYPE_REPLACE); - fullscreen_controller_->OnTabClosing(old_contents); + exclusive_access_manager_->OnTabClosing(old_contents); SessionService* session_service = SessionServiceFactory::GetForProfile(profile_); if (session_service) @@ -1180,10 +1182,10 @@ bool Browser::PreHandleKeyboardEvent(content::WebContents* source, const NativeWebKeyboardEvent& event, bool* is_keyboard_shortcut) { - // Escape exits tabbed fullscreen mode. + // Escape exits tabbed fullscreen mode and mouse lock, and possibly others. // TODO(koz): Write a test for this http://crbug.com/100441. if (event.windowsKeyCode == 27 && - fullscreen_controller_->HandleUserPressedEscape()) { + exclusive_access_manager_->HandleUserPressedEscape()) { return true; } return window()->PreHandleKeyboardEvent(event, is_keyboard_shortcut); @@ -1261,7 +1263,7 @@ } bool Browser::IsMouseLocked() const { - return fullscreen_controller_->IsMouseLocked(); + return exclusive_access_manager_->mouse_lock_controller()->IsMouseLocked(); } void Browser::OnWindowDidShow() { @@ -1665,16 +1667,19 @@ void Browser::EnterFullscreenModeForTab(WebContents* web_contents, const GURL& origin) { - fullscreen_controller_->EnterFullscreenModeForTab(web_contents, origin); + exclusive_access_manager_->fullscreen_controller()->EnterFullscreenModeForTab( + web_contents, origin); } void Browser::ExitFullscreenModeForTab(WebContents* web_contents) { - fullscreen_controller_->ExitFullscreenModeForTab(web_contents); + exclusive_access_manager_->fullscreen_controller()->ExitFullscreenModeForTab( + web_contents); } bool Browser::IsFullscreenForTabOrPending( const WebContents* web_contents) const { - return fullscreen_controller_->IsFullscreenForTabOrPending(web_contents); + return exclusive_access_manager_->fullscreen_controller() + ->IsFullscreenForTabOrPending(web_contents); } void Browser::RegisterProtocolHandler(WebContents* web_contents, @@ -1770,13 +1775,12 @@ void Browser::RequestToLockMouse(WebContents* web_contents, bool user_gesture, bool last_unlocked_by_target) { - fullscreen_controller_->RequestToLockMouse(web_contents, - user_gesture, - last_unlocked_by_target); + exclusive_access_manager_->mouse_lock_controller()->RequestToLockMouse( + web_contents, user_gesture, last_unlocked_by_target); } void Browser::LostMouseLock() { - fullscreen_controller_->LostMouseLock(); + exclusive_access_manager_->mouse_lock_controller()->LostMouseLock(); } void Browser::RequestMediaAccessPermission(
diff --git a/chrome/browser/ui/browser.h b/chrome/browser/ui/browser.h index e7aff35..b4b30335 100644 --- a/chrome/browser/ui/browser.h +++ b/chrome/browser/ui/browser.h
@@ -24,6 +24,7 @@ #include "chrome/browser/ui/bookmarks/bookmark_tab_helper_delegate.h" #include "chrome/browser/ui/browser_navigator.h" #include "chrome/browser/ui/chrome_web_modal_dialog_manager_delegate.h" +#include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" #include "chrome/browser/ui/host_desktop.h" #include "chrome/browser/ui/search/search_tab_helper_delegate.h" #include "chrome/browser/ui/search_engines/search_engine_tab_helper_delegate.h" @@ -57,7 +58,6 @@ class BrowserTabRestoreServiceDelegate; class BrowserWindow; class FindBarController; -class FullscreenController; class PrefService; class Profile; class SearchDelegate; @@ -475,8 +475,8 @@ // Show a download on the download shelf. void ShowDownload(content::DownloadItem* download); - FullscreenController* fullscreen_controller() const { - return fullscreen_controller_.get(); + ExclusiveAccessManager* exclusive_access_manager() { + return exclusive_access_manager_.get(); } extensions::WindowController* extension_window_controller() const { @@ -954,7 +954,7 @@ BookmarkBar::State bookmark_bar_state_; - scoped_ptr<FullscreenController> fullscreen_controller_; + scoped_ptr<ExclusiveAccessManager> exclusive_access_manager_; scoped_ptr<extensions::WindowController> extension_window_controller_;
diff --git a/chrome/browser/ui/browser_command_controller.cc b/chrome/browser/ui/browser_command_controller.cc index b0ce210..49486f6b 100644 --- a/chrome/browser/ui/browser_command_controller.cc +++ b/chrome/browser/ui/browser_command_controller.cc
@@ -760,7 +760,7 @@ ShowHelp(browser_, HELP_SOURCE_MENU); break; case IDC_SHOW_SIGNIN: - ShowBrowserSignin(browser_, signin_metrics::SOURCE_MENU); + ShowBrowserSigninOrSettings(browser_, signin_metrics::SOURCE_MENU); break; case IDC_TOGGLE_SPEECH_INPUT: ToggleSpeechInput(browser_);
diff --git a/chrome/browser/ui/browser_commands.cc b/chrome/browser/ui/browser_commands.cc index a9f6f9b..b3f36a6f 100644 --- a/chrome/browser/ui/browser_commands.cc +++ b/chrome/browser/ui/browser_commands.cc
@@ -1130,7 +1130,9 @@ void ToggleFullscreenMode(Browser* browser) { DCHECK(browser); - browser->fullscreen_controller()->ToggleBrowserFullscreenMode(); + browser->exclusive_access_manager() + ->fullscreen_controller() + ->ToggleBrowserFullscreenMode(); } void ClearCache(Browser* browser) {
diff --git a/chrome/browser/ui/browser_commands_mac.cc b/chrome/browser/ui/browser_commands_mac.cc index 49745240..1cf43c6 100644 --- a/chrome/browser/ui/browser_commands_mac.cc +++ b/chrome/browser/ui/browser_commands_mac.cc
@@ -16,7 +16,9 @@ void ToggleFullscreenWithToolbarOrFallback(Browser* browser) { DCHECK(browser); if (chrome::mac::SupportsSystemFullscreen()) - browser->fullscreen_controller()->ToggleBrowserFullscreenWithToolbar(); + browser->exclusive_access_manager() + ->fullscreen_controller() + ->ToggleBrowserFullscreenWithToolbar(); else ToggleFullscreenMode(browser); }
diff --git a/chrome/browser/ui/browser_mac.cc b/chrome/browser/ui/browser_mac.cc index c7455fb0..96068352 100644 --- a/chrome/browser/ui/browser_mac.cc +++ b/chrome/browser/ui/browser_mac.cc
@@ -55,7 +55,7 @@ Browser* browser = new Browser(Browser::CreateParams(profile, chrome::HOST_DESKTOP_TYPE_NATIVE)); - ShowBrowserSignin(browser, source); + ShowBrowserSigninOrSettings(browser, source); browser->window()->Show(); }
diff --git a/chrome/browser/ui/browser_win.cc b/chrome/browser/ui/browser_win.cc index d655621f..ad4bdab 100644 --- a/chrome/browser/ui/browser_win.cc +++ b/chrome/browser/ui/browser_win.cc
@@ -7,5 +7,5 @@ #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" void Browser::SetMetroSnapMode(bool enable) { - fullscreen_controller_->SetMetroSnapMode(enable); + exclusive_access_manager_->fullscreen_controller()->SetMetroSnapMode(enable); }
diff --git a/chrome/browser/ui/chrome_pages.cc b/chrome/browser/ui/chrome_pages.cc index bf306abd..99bbac23 100644 --- a/chrome/browser/ui/chrome_pages.cc +++ b/chrome/browser/ui/chrome_pages.cc
@@ -334,35 +334,43 @@ SigninManagerBase* manager = SigninManagerFactory::GetForProfile(original_profile); DCHECK(manager->IsSigninAllowed()); - // If we're signed in, just show settings. - if (manager->IsAuthenticated()) { - ShowSettings(browser); - } else { - // If the browser's profile is an incognito profile, make sure to use - // a browser window from the original profile. The user cannot sign in - // from an incognito window. - scoped_ptr<ScopedTabbedBrowserDisplayer> displayer; - if (browser->profile()->IsOffTheRecord()) { - displayer.reset(new ScopedTabbedBrowserDisplayer( - original_profile, chrome::HOST_DESKTOP_TYPE_NATIVE)); - browser = displayer->browser(); - } - - signin_metrics::LogSigninSource(source); - - // Since the app launcher is a separate application, it might steal focus - // away from Chrome, and accidentally close the avatar bubble. In this case, - // fallback to the full-tab signin page. - if (switches::IsNewAvatarMenu() && - source != signin_metrics::SOURCE_APP_LAUNCHER) { - browser->window()->ShowAvatarBubbleFromAvatarButton( - BrowserWindow::AVATAR_BUBBLE_MODE_SIGNIN, - signin::ManageAccountsParams()); - } else { - NavigateToSingletonTab(browser, GURL(signin::GetPromoURL(source, false))); - DCHECK_GT(browser->tab_strip_model()->count(), 0); - } + // If the browser's profile is an incognito profile, make sure to use + // a browser window from the original profile. The user cannot sign in + // from an incognito window. + scoped_ptr<ScopedTabbedBrowserDisplayer> displayer; + if (browser->profile()->IsOffTheRecord()) { + displayer.reset(new ScopedTabbedBrowserDisplayer( + original_profile, chrome::HOST_DESKTOP_TYPE_NATIVE)); + browser = displayer->browser(); } + + signin_metrics::LogSigninSource(source); + + // Since the app launcher is a separate application, it might steal focus + // away from Chrome, and accidentally close the avatar bubble. In this case, + // fallback to the full-tab signin page. + if (switches::IsNewAvatarMenu() && + source != signin_metrics::SOURCE_APP_LAUNCHER) { + browser->window()->ShowAvatarBubbleFromAvatarButton( + BrowserWindow::AVATAR_BUBBLE_MODE_SIGNIN, + signin::ManageAccountsParams()); + } else { + NavigateToSingletonTab(browser, GURL(signin::GetPromoURL(source, false))); + DCHECK_GT(browser->tab_strip_model()->count(), 0); + } +} + +void ShowBrowserSigninOrSettings( + Browser* browser, + signin_metrics::Source source) { + Profile* original_profile = browser->profile()->GetOriginalProfile(); + SigninManagerBase* manager = + SigninManagerFactory::GetForProfile(original_profile); + DCHECK(manager->IsSigninAllowed()); + if (manager->IsAuthenticated()) + ShowSettings(browser); + else + ShowBrowserSignin(browser, source); } #endif
diff --git a/chrome/browser/ui/chrome_pages.h b/chrome/browser/ui/chrome_pages.h index 63c6f66..2dc9fea 100644 --- a/chrome/browser/ui/chrome_pages.h +++ b/chrome/browser/ui/chrome_pages.h
@@ -82,9 +82,13 @@ void ShowSearchEngineSettings(Browser* browser); #if !defined(OS_ANDROID) && !defined(OS_IOS) -// If the user is already signed in, shows the "Signin" portion of Settings, -// otherwise initiates signin. +// Initiates signin in a new browser tab. void ShowBrowserSignin(Browser* browser, signin_metrics::Source source); + +// If the user is already signed in, shows the "Signin" portion of Settings, +// otherwise initiates signin in a new browser tab. +void ShowBrowserSigninOrSettings(Browser* browser, + signin_metrics::Source source); #endif } // namespace chrome
diff --git a/chrome/browser/ui/cocoa/apps/quit_with_apps_controller_mac.cc b/chrome/browser/ui/cocoa/apps/quit_with_apps_controller_mac.cc index 7c09672..27600e8 100644 --- a/chrome/browser/ui/cocoa/apps/quit_with_apps_controller_mac.cc +++ b/chrome/browser/ui/cocoa/apps/quit_with_apps_controller_mac.cc
@@ -73,7 +73,6 @@ l10n_util::GetStringUTF16(IDS_QUIT_WITH_APPS_EXPLANATION), ui::ResourceBundle::GetSharedInstance().GetImageNamed( IDR_PRODUCT_LOGO_128), - blink::WebTextDirectionDefault, message_center::NotifierId(message_center::NotifierId::SYSTEM_COMPONENT, kQuitWithAppsNotificationID), l10n_util::GetStringUTF16(IDS_QUIT_WITH_APPS_NOTIFICATION_DISPLAY_SOURCE),
diff --git a/chrome/browser/ui/cocoa/browser_window_cocoa.mm b/chrome/browser/ui/cocoa/browser_window_cocoa.mm index 456a27e..0079cf18 100644 --- a/chrome/browser/ui/cocoa/browser_window_cocoa.mm +++ b/chrome/browser/ui/cocoa/browser_window_cocoa.mm
@@ -361,7 +361,9 @@ void BrowserWindowCocoa::EnterFullscreen(const GURL& url, ExclusiveAccessBubbleType bubble_type, bool with_toolbar) { - if (browser_->fullscreen_controller()->IsWindowFullscreenForTabOrPending()) + if (browser_->exclusive_access_manager() + ->fullscreen_controller() + ->IsWindowFullscreenForTabOrPending()) [controller_ enterWebContentFullscreenForURL:url bubbleType:bubble_type]; else if (!url.is_empty()) [controller_ enterExtensionFullscreenForURL:url bubbleType:bubble_type]; @@ -515,16 +517,16 @@ [alert addButtonWithTitle:l10n_util::GetNSString(IDS_CANCEL)]; [cancel_button setKeyEquivalent:kKeyEquivalentEscape]; - base::scoped_nsobject<NSButton> open_as_tab_checkbox( + base::scoped_nsobject<NSButton> open_as_window_checkbox( [[NSButton alloc] initWithFrame:NSZeroRect]); - [open_as_tab_checkbox setButtonType:NSSwitchButton]; - [open_as_tab_checkbox - setTitle:l10n_util::GetNSString(IDS_BOOKMARK_APP_BUBBLE_OPEN_AS_TAB)]; - [open_as_tab_checkbox setState: + [open_as_window_checkbox setButtonType:NSSwitchButton]; + [open_as_window_checkbox + setTitle:l10n_util::GetNSString(IDS_BOOKMARK_APP_BUBBLE_OPEN_AS_WINDOW)]; + [open_as_window_checkbox setState: profile->GetPrefs()->GetInteger( extensions::pref_names::kBookmarkAppCreationLaunchType) == - extensions::LAUNCH_TYPE_REGULAR]; - [open_as_tab_checkbox sizeToFit]; + extensions::LAUNCH_TYPE_WINDOW]; + [open_as_window_checkbox sizeToFit]; base::scoped_nsobject<NSTextField> app_title([[NSTextField alloc] initWithFrame:NSMakeRect(0, kAppTextFieldHeight + @@ -538,7 +540,7 @@ base::scoped_nsobject<NSView> view([[NSView alloc] initWithFrame:NSMakeRect(0, 0, kBookmarkAppBubbleViewWidth, kBookmarkAppBubbleViewHeight)]); - [view addSubview:open_as_tab_checkbox]; + [view addSubview:open_as_window_checkbox]; [view addSubview:app_title]; [alert setAccessoryView:view]; @@ -560,12 +562,12 @@ if ([alert runModal] == NSAlertFirstButtonReturn) { // Save launch type preferences for later when creating another hosted app. extensions::LaunchType launch_type = - [open_as_tab_checkbox state] == NSOnState - ? extensions::LAUNCH_TYPE_REGULAR - : extensions::LAUNCH_TYPE_WINDOW; + [open_as_window_checkbox state] == NSOnState + ? extensions::LAUNCH_TYPE_WINDOW + : extensions::LAUNCH_TYPE_REGULAR; profile->GetPrefs()->SetInteger( extensions::pref_names::kBookmarkAppCreationLaunchType, launch_type); - extensions::SetLaunchType(service, extension_id, launch_type); + extensions::SetLaunchType(profile, extension_id, launch_type); // Update name of app. NSString* new_title = [app_title stringValue];
diff --git a/chrome/browser/ui/cocoa/browser_window_controller.mm b/chrome/browser/ui/cocoa/browser_window_controller.mm index 5fde5b9..6bc6bde 100644 --- a/chrome/browser/ui/cocoa/browser_window_controller.mm +++ b/chrome/browser/ui/cocoa/browser_window_controller.mm
@@ -255,7 +255,10 @@ // Make the content view for the window have a layer. This will make all // sub-views have layers. This is necessary to ensure correct layer // ordering of all child views and their layers. - [[window contentView] setWantsLayer:YES]; + if ([self wantsRootViewToBeLayerBacked]) + [[[window contentView] superview] setWantsLayer:YES]; + else + [[window contentView] setWantsLayer:YES]; windowShim_.reset(new BrowserWindowCocoa(browser, self)); // Set different minimum sizes on tabbed windows vs non-tabbed, e.g. popups.
diff --git a/chrome/browser/ui/cocoa/browser_window_controller_private.h b/chrome/browser/ui/cocoa/browser_window_controller_private.h index 341c428..6733fc34 100644 --- a/chrome/browser/ui/cocoa/browser_window_controller_private.h +++ b/chrome/browser/ui/cocoa/browser_window_controller_private.h
@@ -159,6 +159,9 @@ // out of AppKit Fullscreen. - (BOOL)shouldUseCustomAppKitFullscreenTransition; +// Whether the root view of the window should be layer backed. +- (BOOL)wantsRootViewToBeLayerBacked; + @end // @interface BrowserWindowController(Private) #endif // CHROME_BROWSER_UI_COCOA_BROWSER_WINDOW_CONTROLLER_PRIVATE_H_
diff --git a/chrome/browser/ui/cocoa/browser_window_controller_private.mm b/chrome/browser/ui/cocoa/browser_window_controller_private.mm index f2c086b0..b82ea10 100644 --- a/chrome/browser/ui/cocoa/browser_window_controller_private.mm +++ b/chrome/browser/ui/cocoa/browser_window_controller_private.mm
@@ -426,8 +426,9 @@ } - (void)configurePresentationModeController { - BOOL fullscreen_for_tab = - browser_->fullscreen_controller()->IsWindowFullscreenForTabOrPending(); + BOOL fullscreen_for_tab = browser_->exclusive_access_manager() + ->fullscreen_controller() + ->IsWindowFullscreenForTabOrPending(); BOOL kiosk_mode = base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kKioskMode); BOOL showDropdown = @@ -670,7 +671,9 @@ NSWindow* window = [self window]; savedRegularWindowFrame_ = [window frame]; BOOL mode = enteringPresentationMode_ || - browser_->fullscreen_controller()->IsWindowFullscreenForTabOrPending(); + browser_->exclusive_access_manager() + ->fullscreen_controller() + ->IsWindowFullscreenForTabOrPending(); enteringAppKitFullscreen_ = YES; enteringAppKitFullscreenOnPrimaryScreen_ = [[[self window] screen] isEqual:[[NSScreen screens] objectAtIndex:0]]; @@ -1069,4 +1072,16 @@ return [super shouldConstrainFrameRect]; } +- (BOOL)wantsRootViewToBeLayerBacked { + // This class always layer-backs the contentView of the window. If Chrome + // were linked against OSX 10.9, this would also cause the root view to be + // layer backed. Since Chrome is linked against OSX 10.6, the root view by + // default is not layer backed. + + // This class is going to have a custom AppKit fullscreen animation, which + // requires that the root view is layer backed. To be safe, this class will + // only layer-back the root view on OSX 10.9+. + return base::mac::IsOSMavericksOrLater(); +} + @end // @implementation BrowserWindowController(Private)
diff --git a/chrome/browser/ui/cocoa/exclusive_access_bubble_window_controller.mm b/chrome/browser/ui/cocoa/exclusive_access_bubble_window_controller.mm index d6c0de16..6274888 100644 --- a/chrome/browser/ui/cocoa/exclusive_access_bubble_window_controller.mm +++ b/chrome/browser/ui/cocoa/exclusive_access_bubble_window_controller.mm
@@ -96,12 +96,12 @@ [[self window] setIgnoresMouseEvents:YES]; DCHECK(exclusive_access_bubble::ShowButtonsForType(bubbleType_)); - browser_->fullscreen_controller()->OnAcceptFullscreenPermission(); + browser_->exclusive_access_manager()->OnAcceptExclusiveAccessPermission(); } - (void)deny:(id)sender { DCHECK(exclusive_access_bubble::ShowButtonsForType(bubbleType_)); - browser_->fullscreen_controller()->OnDenyFullscreenPermission(); + browser_->exclusive_access_manager()->OnDenyExclusiveAccessPermission(); } - (void)showButtons:(BOOL)show { @@ -151,8 +151,9 @@ - (BOOL)textView:(NSTextView*)textView clickedOnLink:(id)link atIndex:(NSUInteger)charIndex { - browser_->fullscreen_controller() - ->ExitTabOrBrowserFullscreenToPreviousState(); + browser_->exclusive_access_manager() + ->fullscreen_controller() + ->ExitExclusiveAccessToPreviousState(); return YES; }
diff --git a/chrome/browser/ui/cocoa/javascript_app_modal_dialog_cocoa.mm b/chrome/browser/ui/cocoa/javascript_app_modal_dialog_cocoa.mm index 287a887..73ee1c6 100644 --- a/chrome/browser/ui/cocoa/javascript_app_modal_dialog_cocoa.mm +++ b/chrome/browser/ui/cocoa/javascript_app_modal_dialog_cocoa.mm
@@ -16,6 +16,8 @@ #include "components/app_modal/javascript_app_modal_dialog.h" #include "components/app_modal/javascript_dialog_manager.h" #include "components/app_modal/javascript_native_dialog_factory.h" +#include "content/public/browser/web_contents.h" +#include "content/public/browser/web_contents_delegate.h" #include "grit/components_strings.h" #include "ui/base/l10n/l10n_util_mac.h" #include "ui/base/ui_base_types.h" @@ -457,9 +459,12 @@ private: app_modal::NativeAppModalDialog* CreateNativeJavaScriptDialog( - app_modal::JavaScriptAppModalDialog* dialog, - gfx::NativeWindow parent_window) override { - return new JavaScriptAppModalDialogCocoa(dialog); + app_modal::JavaScriptAppModalDialog* dialog) override { + app_modal::NativeAppModalDialog* d = + new JavaScriptAppModalDialogCocoa(dialog); + dialog->web_contents()->GetDelegate()->ActivateContents( + dialog->web_contents()); + return d; } DISALLOW_COPY_AND_ASSIGN(ChromeJavaScriptNativeDialogCocoaFactory);
diff --git a/chrome/browser/ui/cocoa/profiles/user_manager_mac.h b/chrome/browser/ui/cocoa/profiles/user_manager_mac.h index 6a1080aa..6de2648 100644 --- a/chrome/browser/ui/cocoa/profiles/user_manager_mac.h +++ b/chrome/browser/ui/cocoa/profiles/user_manager_mac.h
@@ -28,10 +28,10 @@ // controller destroyed itself. Deletes the instance. void WindowWasClosed(); - // Called from the UserManager class once the |guest_profile| is ready. Will + // Called from the UserManager class once the |system_profile| is ready. Will // construct a UserManagerMac object and show |url|. - static void OnGuestProfileCreated(Profile* guest_profile, - const std::string& url); + static void OnSystemProfileCreated(Profile* system_profile, + const std::string& url); UserManagerWindowController* window_controller() { return window_controller_.get();
diff --git a/chrome/browser/ui/cocoa/profiles/user_manager_mac.mm b/chrome/browser/ui/cocoa/profiles/user_manager_mac.mm index a4ec2e9c..89fd112 100644 --- a/chrome/browser/ui/cocoa/profiles/user_manager_mac.mm +++ b/chrome/browser/ui/cocoa/profiles/user_manager_mac.mm
@@ -182,11 +182,11 @@ // Create the guest profile, if necessary, and open the User Manager // from the guest profile. - profiles::CreateGuestProfileForUserManager( + profiles::CreateSystemProfileForUserManager( profile_path_to_focus, tutorial_mode, profile_open_action, - base::Bind(&UserManagerMac::OnGuestProfileCreated)); + base::Bind(&UserManagerMac::OnSystemProfileCreated)); } void UserManager::Hide() { @@ -207,10 +207,10 @@ } // static -void UserManagerMac::OnGuestProfileCreated(Profile* guest_profile, - const std::string& url) { +void UserManagerMac::OnSystemProfileCreated(Profile* system_profile, + const std::string& url) { DCHECK(!instance_); - instance_ = new UserManagerMac(guest_profile); + instance_ = new UserManagerMac(system_profile); [instance_->window_controller() showURL:GURL(url)]; }
diff --git a/chrome/browser/ui/cocoa/profiles/user_manager_mac_unittest.mm b/chrome/browser/ui/cocoa/profiles/user_manager_mac_unittest.mm index 820f33e..4444f1f 100644 --- a/chrome/browser/ui/cocoa/profiles/user_manager_mac_unittest.mm +++ b/chrome/browser/ui/cocoa/profiles/user_manager_mac_unittest.mm
@@ -20,13 +20,13 @@ void SetUp() override { BrowserWithTestWindowTest::SetUp(); ASSERT_TRUE(testing_profile_manager_.SetUp()); - // Pre-load the guest profile so we don't have to wait for the User Manager + // Pre-load the system profile so we don't have to wait for the User Manager // to asynchronously create it. - testing_profile_manager_.CreateGuestProfile(); + testing_profile_manager_.CreateSystemProfile(); } void TearDown() override { - testing_profile_manager_.DeleteGuestProfile(); + testing_profile_manager_.DeleteSystemProfile(); TestingBrowserProcess::GetGlobal()->SetProfileManager(NULL); base::RunLoop().RunUntilIdle(); BrowserWithTestWindowTest::TearDown();
diff --git a/chrome/browser/ui/exclusive_access/exclusive_access_bubble.cc b/chrome/browser/ui/exclusive_access/exclusive_access_bubble.cc index 35830240..178e97d 100644 --- a/chrome/browser/ui/exclusive_access/exclusive_access_bubble.cc +++ b/chrome/browser/ui/exclusive_access/exclusive_access_bubble.cc
@@ -115,16 +115,17 @@ } void ExclusiveAccessBubble::ToggleFullscreen() { - browser_->fullscreen_controller() - ->ExitTabOrBrowserFullscreenToPreviousState(); + browser_->exclusive_access_manager() + ->fullscreen_controller() + ->ExitExclusiveAccessToPreviousState(); } void ExclusiveAccessBubble::Accept() { - browser_->fullscreen_controller()->OnAcceptFullscreenPermission(); + browser_->exclusive_access_manager()->OnAcceptExclusiveAccessPermission(); } void ExclusiveAccessBubble::Cancel() { - browser_->fullscreen_controller()->OnDenyFullscreenPermission(); + browser_->exclusive_access_manager()->OnDenyExclusiveAccessPermission(); } base::string16 ExclusiveAccessBubble::GetCurrentMessageText() const {
diff --git a/chrome/browser/ui/exclusive_access/exclusive_access_controller_base.cc b/chrome/browser/ui/exclusive_access/exclusive_access_controller_base.cc new file mode 100644 index 0000000..db8a243c --- /dev/null +++ b/chrome/browser/ui/exclusive_access/exclusive_access_controller_base.cc
@@ -0,0 +1,93 @@ +// Copyright (c) 2015 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/exclusive_access/exclusive_access_controller_base.h" + +#include "chrome/browser/chrome_notification_types.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_window.h" +#include "content/public/browser/navigation_details.h" +#include "content/public/browser/navigation_entry.h" +#include "content/public/browser/notification_service.h" +#include "content/public/browser/web_contents.h" + +using content::WebContents; + +ExclusiveAccessControllerBase::ExclusiveAccessControllerBase( + ExclusiveAccessManager* manager, + Browser* browser) + : manager_(manager), + browser_(browser), + profile_(browser->profile()), + tab_with_exclusive_access_(nullptr) { + DCHECK(profile_); +} + +ExclusiveAccessControllerBase::~ExclusiveAccessControllerBase() { +} + +GURL ExclusiveAccessControllerBase::GetExclusiveAccessBubbleURL() const { + return manager_->GetExclusiveAccessBubbleURL(); +} + +GURL ExclusiveAccessControllerBase::GetURLForExclusiveAccessBubble() const { + if (tab_with_exclusive_access_) + return tab_with_exclusive_access_->GetURL(); + return GURL(); +} + +void ExclusiveAccessControllerBase::OnTabDeactivated( + WebContents* web_contents) { + if (web_contents == tab_with_exclusive_access_) + ExitExclusiveAccessIfNecessary(); +} + +void ExclusiveAccessControllerBase::OnTabDetachedFromView( + WebContents* old_contents) { + // Derived class will have to implement if necessary. +} + +void ExclusiveAccessControllerBase::OnTabClosing(WebContents* web_contents) { + if (web_contents == tab_with_exclusive_access_) { + ExitExclusiveAccessIfNecessary(); + + // The call to exit exclusive access may result in asynchronous notification + // of state change (e.g. fullscreen change on Linux). We don't want to rely + // on it to call NotifyTabExclusiveAccessLost(), because at that point + // |tab_with_exclusive_access_| may not be valid. Instead, we call it here + // to clean up exclusive access tab related state. + NotifyTabExclusiveAccessLost(); + } +} + +void ExclusiveAccessControllerBase::Observe( + int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) { + DCHECK_EQ(content::NOTIFICATION_NAV_ENTRY_COMMITTED, type); + if (content::Details<content::LoadCommittedDetails>(details) + ->is_navigation_to_different_page()) + ExitExclusiveAccessIfNecessary(); +} + +void ExclusiveAccessControllerBase::SetTabWithExclusiveAccess( + WebContents* tab) { + // Tab should never be replaced with another tab, or + // UpdateNotificationRegistrations would need updating. + DCHECK(tab_with_exclusive_access_ == tab || + tab_with_exclusive_access_ == nullptr || tab == nullptr); + tab_with_exclusive_access_ = tab; + UpdateNotificationRegistrations(); +} + +void ExclusiveAccessControllerBase::UpdateNotificationRegistrations() { + if (tab_with_exclusive_access_ && registrar_.IsEmpty()) { + registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, + content::Source<content::NavigationController>( + &tab_with_exclusive_access_->GetController())); + } else if (!tab_with_exclusive_access_ && !registrar_.IsEmpty()) { + registrar_.RemoveAll(); + } +}
diff --git a/chrome/browser/ui/exclusive_access/exclusive_access_controller_base.h b/chrome/browser/ui/exclusive_access/exclusive_access_controller_base.h new file mode 100644 index 0000000..99c5614 --- /dev/null +++ b/chrome/browser/ui/exclusive_access/exclusive_access_controller_base.h
@@ -0,0 +1,101 @@ +// Copyright (c) 2015 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_EXCLUSIVE_ACCESS_EXCLUSIVE_ACCESS_CONTROLLER_BASE_H_ +#define CHROME_BROWSER_UI_EXCLUSIVE_ACCESS_EXCLUSIVE_ACCESS_CONTROLLER_BASE_H_ + +#include "base/basictypes.h" +#include "base/memory/weak_ptr.h" +#include "chrome/browser/ui/exclusive_access/exclusive_access_bubble_type.h" +#include "content/public/browser/notification_observer.h" +#include "content/public/browser/notification_registrar.h" + +class Browser; +class BrowserWindow; +class ExclusiveAccessManager; +class GURL; +class Profile; + +namespace content { +class WebContents; +} + +// The base class for the different exclusive access controllers like the +// FullscreenController, and MouseLockController which controls lifetime for +// which the resource (screen/mouse) is held exclusively. +class ExclusiveAccessControllerBase : public content::NotificationObserver { + public: + explicit ExclusiveAccessControllerBase(ExclusiveAccessManager* manager, + Browser* browser); + ~ExclusiveAccessControllerBase() override; + + GURL GetExclusiveAccessBubbleURL() const; + virtual GURL GetURLForExclusiveAccessBubble() const; + + content::WebContents* exclusive_access_tab() const { + return tab_with_exclusive_access_; + } + + // Functions implemented by derived classes: + + // Control behavior when escape is pressed returning true if it was handled. + virtual bool HandleUserPressedEscape() = 0; + + // Called by Browser in response to call from ExclusiveAccessBubble. + virtual void ExitExclusiveAccessToPreviousState() = 0; + + // Called to indicate that the permission for this exclusive access has been + // granted if requested. Returns true if the exit bubble content should be + // updated. + virtual bool OnAcceptExclusiveAccessPermission() = 0; + + // Called to indicate that the permission for the exclusive access has been + // denied if requested. Returns true if the exit bubble content should be + // updated. + virtual bool OnDenyExclusiveAccessPermission() = 0; + + // Called by ExclusiveAccessManager in response to calls from Browser. + virtual void OnTabDeactivated(content::WebContents* web_contents); + virtual void OnTabDetachedFromView(content::WebContents* web_contents); + virtual void OnTabClosing(content::WebContents* web_contents); + + // Callbacks //////////////////////////////////////////////////////////////// + + // content::NotificationObserver to detect page navigation and exit exclusive + // access. + void Observe(int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) override; + + protected: + void SetTabWithExclusiveAccess(content::WebContents* tab); + + ExclusiveAccessManager* exclusive_access_manager() const { return manager_; } + + Browser* browser() const { return browser_; } + + Profile* profile() const { return profile_; } + + // Exits exclusive access mode for the tab if currently exclusive. + virtual void ExitExclusiveAccessIfNecessary() = 0; + + // Notifies the tab that it has been forced out of exclusive access mode + // if necessary. + virtual void NotifyTabExclusiveAccessLost() = 0; + + private: + void UpdateNotificationRegistrations(); + + ExclusiveAccessManager* const manager_; + Browser* const browser_; + Profile* const profile_; + + content::NotificationRegistrar registrar_; + + content::WebContents* tab_with_exclusive_access_; + + DISALLOW_COPY_AND_ASSIGN(ExclusiveAccessControllerBase); +}; + +#endif // CHROME_BROWSER_UI_EXCLUSIVE_ACCESS_EXCLUSIVE_ACCESS_CONTROLLER_BASE_H_
diff --git a/chrome/browser/ui/exclusive_access/exclusive_access_manager.cc b/chrome/browser/ui/exclusive_access/exclusive_access_manager.cc new file mode 100644 index 0000000..56a8cc6 --- /dev/null +++ b/chrome/browser/ui/exclusive_access/exclusive_access_manager.cc
@@ -0,0 +1,119 @@ +// Copyright (c) 2015 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/exclusive_access/exclusive_access_manager.h" + +#include "chrome/browser/app_mode/app_mode_utils.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" +#include "chrome/browser/ui/exclusive_access/mouse_lock_controller.h" + +using content::WebContents; + +ExclusiveAccessManager::ExclusiveAccessManager(Browser* browser) + : browser_(browser), + fullscreen_controller_(this, browser), + mouse_lock_controller_(this, browser) { +} + +ExclusiveAccessManager::~ExclusiveAccessManager() { +} + +ExclusiveAccessBubbleType +ExclusiveAccessManager::GetExclusiveAccessExitBubbleType() const { + // In kiosk and exclusive app mode we always want to be fullscreen and do not + // want to show exit instructions for browser mode fullscreen. + bool app_mode = false; +#if !defined(OS_MACOSX) // App mode (kiosk) is not available on Mac yet. + app_mode = chrome::IsRunningInAppMode(); +#endif + + if (mouse_lock_controller_.IsMouseLockSilentlyAccepted() && + (!fullscreen_controller_.IsWindowFullscreenForTabOrPending() || + fullscreen_controller_.IsUserAcceptedFullscreen())) + return EXCLUSIVE_ACCESS_BUBBLE_TYPE_NONE; + + if (!fullscreen_controller_.IsWindowFullscreenForTabOrPending()) { + if (mouse_lock_controller_.IsMouseLocked()) + return EXCLUSIVE_ACCESS_BUBBLE_TYPE_MOUSELOCK_EXIT_INSTRUCTION; + if (mouse_lock_controller_.IsMouseLockRequested()) + return EXCLUSIVE_ACCESS_BUBBLE_TYPE_MOUSELOCK_BUTTONS; + if (fullscreen_controller_.IsExtensionFullscreenOrPending()) + return EXCLUSIVE_ACCESS_BUBBLE_TYPE_EXTENSION_FULLSCREEN_EXIT_INSTRUCTION; + if (fullscreen_controller_.IsControllerInitiatedFullscreen() && !app_mode) + return EXCLUSIVE_ACCESS_BUBBLE_TYPE_BROWSER_FULLSCREEN_EXIT_INSTRUCTION; + return EXCLUSIVE_ACCESS_BUBBLE_TYPE_NONE; + } + + if (fullscreen_controller_.IsUserAcceptedFullscreen()) { + if (fullscreen_controller_.IsPrivilegedFullscreenForTab()) + return EXCLUSIVE_ACCESS_BUBBLE_TYPE_NONE; + if (mouse_lock_controller_.IsMouseLocked()) + return EXCLUSIVE_ACCESS_BUBBLE_TYPE_FULLSCREEN_MOUSELOCK_EXIT_INSTRUCTION; + if (mouse_lock_controller_.IsMouseLockRequested()) + return EXCLUSIVE_ACCESS_BUBBLE_TYPE_MOUSELOCK_BUTTONS; + return EXCLUSIVE_ACCESS_BUBBLE_TYPE_FULLSCREEN_EXIT_INSTRUCTION; + } + + if (mouse_lock_controller_.IsMouseLockRequested()) + return EXCLUSIVE_ACCESS_BUBBLE_TYPE_FULLSCREEN_MOUSELOCK_BUTTONS; + return EXCLUSIVE_ACCESS_BUBBLE_TYPE_FULLSCREEN_BUTTONS; +} + +void ExclusiveAccessManager::UpdateExclusiveAccessExitBubbleContent() { + GURL url = GetExclusiveAccessBubbleURL(); + ExclusiveAccessBubbleType bubble_type = GetExclusiveAccessExitBubbleType(); + + // If bubble displays buttons, unlock mouse to allow pressing them. + if (exclusive_access_bubble::ShowButtonsForType(bubble_type) && + mouse_lock_controller_.IsMouseLocked()) + mouse_lock_controller_.UnlockMouse(); + + browser_->window()->UpdateFullscreenExitBubbleContent(url, bubble_type); +} + +GURL ExclusiveAccessManager::GetExclusiveAccessBubbleURL() const { + GURL result = fullscreen_controller_.GetURLForExclusiveAccessBubble(); + if (!result.is_valid()) + result = mouse_lock_controller_.GetURLForExclusiveAccessBubble(); + return result; +} + +void ExclusiveAccessManager::OnTabDeactivated(WebContents* web_contents) { + fullscreen_controller_.OnTabDeactivated(web_contents); + mouse_lock_controller_.OnTabDeactivated(web_contents); +} + +void ExclusiveAccessManager::OnTabDetachedFromView(WebContents* web_contents) { + fullscreen_controller_.OnTabDetachedFromView(web_contents); + mouse_lock_controller_.OnTabDetachedFromView(web_contents); +} + +void ExclusiveAccessManager::OnTabClosing(WebContents* web_contents) { + fullscreen_controller_.OnTabClosing(web_contents); + mouse_lock_controller_.OnTabClosing(web_contents); +} + +bool ExclusiveAccessManager::HandleUserPressedEscape() { + bool handled = false; + handled = fullscreen_controller_.HandleUserPressedEscape(); + handled |= mouse_lock_controller_.HandleUserPressedEscape(); + return handled; +} + +void ExclusiveAccessManager::OnAcceptExclusiveAccessPermission() { + bool updateBubble = + mouse_lock_controller_.OnAcceptExclusiveAccessPermission(); + updateBubble |= fullscreen_controller_.OnAcceptExclusiveAccessPermission(); + if (updateBubble) + UpdateExclusiveAccessExitBubbleContent(); +} + +void ExclusiveAccessManager::OnDenyExclusiveAccessPermission() { + bool updateBubble = mouse_lock_controller_.OnDenyExclusiveAccessPermission(); + updateBubble |= fullscreen_controller_.OnDenyExclusiveAccessPermission(); + if (updateBubble) + UpdateExclusiveAccessExitBubbleContent(); +}
diff --git a/chrome/browser/ui/exclusive_access/exclusive_access_manager.h b/chrome/browser/ui/exclusive_access/exclusive_access_manager.h new file mode 100644 index 0000000..0c10fe5 --- /dev/null +++ b/chrome/browser/ui/exclusive_access/exclusive_access_manager.h
@@ -0,0 +1,69 @@ +// Copyright (c) 2015 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_EXCLUSIVE_ACCESS_EXCLUSIVE_ACCESS_MANAGER_H_ +#define CHROME_BROWSER_UI_EXCLUSIVE_ACCESS_EXCLUSIVE_ACCESS_MANAGER_H_ + +#include "base/memory/scoped_ptr.h" +#include "chrome/browser/ui/exclusive_access/exclusive_access_bubble_type.h" +#include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" +#include "chrome/browser/ui/exclusive_access/mouse_lock_controller.h" + +class Browser; +class FullscreenController; +class GURL; +class MouseLockController; + +namespace content { +class WebContents; +} + +// This class combines the different exclusive access modes (like fullscreen and +// mouse lock) which are each handled by respective controller. It also updates +// the exit bubble to reflect the combined state. +class ExclusiveAccessManager { + public: + explicit ExclusiveAccessManager(Browser* browser); + ~ExclusiveAccessManager(); + + FullscreenController* fullscreen_controller() { + return &fullscreen_controller_; + } + + MouseLockController* mouse_lock_controller() { + return &mouse_lock_controller_; + } + + ExclusiveAccessBubbleType GetExclusiveAccessExitBubbleType() const; + void UpdateExclusiveAccessExitBubbleContent(); + + GURL GetExclusiveAccessBubbleURL() const; + + // Callbacks //////////////////////////////////////////////////////////////// + + // Called by Browser::TabDeactivated. + void OnTabDeactivated(content::WebContents* web_contents); + + // Called by Browser::ActiveTabChanged. + void OnTabDetachedFromView(content::WebContents* web_contents); + + // Called by Browser::TabClosingAt. + void OnTabClosing(content::WebContents* web_contents); + + // Called by Browser::PreHandleKeyboardEvent + bool HandleUserPressedEscape(); + + // Called by platform ExclusiveAccessExitBubble. + void OnAcceptExclusiveAccessPermission(); + void OnDenyExclusiveAccessPermission(); + + private: + Browser* const browser_; + FullscreenController fullscreen_controller_; + MouseLockController mouse_lock_controller_; + + DISALLOW_COPY_AND_ASSIGN(ExclusiveAccessManager); +}; + +#endif // CHROME_BROWSER_UI_EXCLUSIVE_ACCESS_EXCLUSIVE_ACCESS_MANAGER_H_
diff --git a/chrome/browser/ui/exclusive_access/flash_fullscreen_interactive_browsertest.cc b/chrome/browser/ui/exclusive_access/flash_fullscreen_interactive_browsertest.cc index 7102b0e..ef37aa5 100644 --- a/chrome/browser/ui/exclusive_access/flash_fullscreen_interactive_browsertest.cc +++ b/chrome/browser/ui/exclusive_access/flash_fullscreen_interactive_browsertest.cc
@@ -147,8 +147,10 @@ return false; } EXPECT_EQ(GetActiveWebContents()->GetCapturerCount() > 0, - !browser()->fullscreen_controller()-> - IsWindowFullscreenForTabOrPending()); + !browser() + ->exclusive_access_manager() + ->fullscreen_controller() + ->IsWindowFullscreenForTabOrPending()); } return true; @@ -187,8 +189,11 @@ private: bool IsObservingTabInFullscreen(content::WebContents* contents, bool expected_in_fullscreen) const { - return expected_in_fullscreen == browser()->fullscreen_controller()-> - IsFullscreenForTabOrPending(contents); + return expected_in_fullscreen == + browser() + ->exclusive_access_manager() + ->fullscreen_controller() + ->IsFullscreenForTabOrPending(contents); } bool IsObservingFlashHasFocus(content::WebContents* contents,
diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller.cc b/chrome/browser/ui/exclusive_access/fullscreen_controller.cc index 39cdac29..b37d04ce 100644 --- a/chrome/browser/ui/exclusive_access/fullscreen_controller.cc +++ b/chrome/browser/ui/exclusive_access/fullscreen_controller.cc
@@ -37,28 +37,22 @@ using content::RenderViewHost; using content::WebContents; -FullscreenController::FullscreenController(Browser* browser) - : browser_(browser), - window_(browser->window()), - profile_(browser->profile()), - fullscreened_tab_(NULL), +FullscreenController::FullscreenController(ExclusiveAccessManager* manager, + Browser* browser) + : ExclusiveAccessControllerBase(manager, browser), state_prior_to_tab_fullscreen_(STATE_INVALID), tab_fullscreen_accepted_(false), toggled_into_fullscreen_(false), - mouse_lock_tab_(NULL), - mouse_lock_state_(MOUSELOCK_NOT_REQUESTED), reentrant_window_state_change_call_check_(false), is_privileged_fullscreen_for_testing_(false), ptr_factory_(this) { - DCHECK(window_); - DCHECK(profile_); } FullscreenController::~FullscreenController() { } bool FullscreenController::IsFullscreenForBrowser() const { - return window_->IsFullscreen() && !IsFullscreenCausedByTab(); + return browser()->window()->IsFullscreen() && !IsFullscreenCausedByTab(); } void FullscreenController::ToggleBrowserFullscreenMode() { @@ -79,13 +73,26 @@ } bool FullscreenController::IsWindowFullscreenForTabOrPending() const { - return fullscreened_tab_ != NULL; + return exclusive_access_tab() != nullptr; +} + +bool FullscreenController::IsExtensionFullscreenOrPending() const { + return !extension_caused_fullscreen_.is_empty(); +} + +bool FullscreenController::IsControllerInitiatedFullscreen() const { + return toggled_into_fullscreen_; +} + +bool FullscreenController::IsUserAcceptedFullscreen() const { + return tab_fullscreen_accepted_; } bool FullscreenController::IsFullscreenForTabOrPending( const WebContents* web_contents) const { - if (web_contents == fullscreened_tab_) { - DCHECK(web_contents == browser_->tab_strip_model()->GetActiveWebContents()); + if (web_contents == exclusive_access_tab()) { + DCHECK(web_contents == + browser()->tab_strip_model()->GetActiveWebContents()); DCHECK(web_contents->GetCapturerCount() == 0); return true; } @@ -106,7 +113,7 @@ return; } - if (web_contents != browser_->tab_strip_model()->GetActiveWebContents() || + if (web_contents != browser()->tab_strip_model()->GetActiveWebContents() || IsWindowFullscreenForTabOrPending()) { return; } @@ -120,18 +127,21 @@ return; #endif - SetFullscreenedTab(web_contents, origin); + SetTabWithExclusiveAccess(web_contents); + fullscreened_origin_ = origin; - if (!window_->IsFullscreen()) { + BrowserWindow* window = browser()->window(); + + if (!window->IsFullscreen()) { // Normal -> Tab Fullscreen. state_prior_to_tab_fullscreen_ = STATE_NORMAL; ToggleFullscreenModeInternal(TAB); return; } - if (window_->IsFullscreenWithToolbar()) { + if (window->IsFullscreenWithToolbar()) { // Browser Fullscreen with Toolbar -> Tab Fullscreen (no toolbar). - window_->UpdateFullscreenWithToolbar(false); + window->UpdateFullscreenWithToolbar(false); state_prior_to_tab_fullscreen_ = STATE_BROWSER_FULLSCREEN_WITH_TOOLBAR; } else { // Browser Fullscreen without Toolbar -> Tab Fullscreen. @@ -143,7 +153,7 @@ if (!tab_fullscreen_accepted_) { tab_fullscreen_accepted_ = GetFullscreenSetting() == CONTENT_SETTING_ALLOW; } - UpdateFullscreenExitBubbleContent(); + exclusive_access_manager()->UpdateExclusiveAccessExitBubbleContent(); // This is only a change between Browser and Tab fullscreen. We generate // a fullscreen notification now because there is no window change. @@ -158,7 +168,7 @@ } if (!IsWindowFullscreenForTabOrPending() || - web_contents != fullscreened_tab_) { + web_contents != exclusive_access_tab()) { return; } @@ -171,7 +181,8 @@ return; #endif - if (!window_->IsFullscreen()) + BrowserWindow* window = browser()->window(); + if (!window->IsFullscreen()) return; if (IsFullscreenCausedByTab()) { @@ -183,12 +194,12 @@ // Tab Fullscreen -> Browser Fullscreen (with or without toolbar). if (state_prior_to_tab_fullscreen_ == STATE_BROWSER_FULLSCREEN_WITH_TOOLBAR) { // Tab Fullscreen (no toolbar) -> Browser Fullscreen with Toolbar. - window_->UpdateFullscreenWithToolbar(true); + window->UpdateFullscreenWithToolbar(true); } #if defined(OS_MACOSX) // Clear the bubble URL, which forces the Mac UI to redraw. - UpdateFullscreenExitBubbleContent(); + exclusive_access_manager()->UpdateExclusiveAccessExitBubbleContent(); #endif // defined(OS_MACOSX) // If currently there is a tab in "tab fullscreen" mode and fullscreen @@ -196,7 +207,7 @@ // mode), we need to switch back to "browser fullscreen" mode. In this // case, all we have to do is notifying the tab that it has exited "tab // fullscreen" mode. - NotifyTabOfExitIfNecessary(); + NotifyTabExclusiveAccessLost(); // This is only a change between Browser and Tab fullscreen. We generate // a fullscreen notification now because there is no window change. @@ -205,7 +216,7 @@ bool FullscreenController::IsInMetroSnapMode() { #if defined(OS_WIN) - return window_->IsInMetroSnapMode(); + return browser()->window()->IsInMetroSnapMode(); #else return false; #endif @@ -216,7 +227,7 @@ reentrant_window_state_change_call_check_ = false; toggled_into_fullscreen_ = false; - window_->SetMetroSnapMode(enable); + browser()->window()->SetMetroSnapMode(enable); // FullscreenController unit tests for metro snap assume that on Windows calls // to WindowFullscreenStateChanged are reentrant. If that assumption is @@ -225,73 +236,6 @@ } #endif // defined(OS_WIN) -bool FullscreenController::IsMouseLockRequested() const { - return mouse_lock_state_ == MOUSELOCK_REQUESTED; -} - -bool FullscreenController::IsMouseLocked() const { - return mouse_lock_state_ == MOUSELOCK_ACCEPTED || - mouse_lock_state_ == MOUSELOCK_ACCEPTED_SILENTLY; -} - -void FullscreenController::RequestToLockMouse(WebContents* web_contents, - bool user_gesture, - bool last_unlocked_by_target) { - DCHECK(!IsMouseLocked()); - NotifyMouseLockChange(); - - // Must have a user gesture to prevent misbehaving sites from constantly - // re-locking the mouse. Exceptions are when the page has unlocked - // (i.e. not the user), or if we're in tab fullscreen (user gesture required - // for that) - if (!last_unlocked_by_target && !user_gesture && - !IsFullscreenForTabOrPending(web_contents)) { - web_contents->GotResponseToLockMouseRequest(false); - return; - } - SetMouseLockTab(web_contents); - ExclusiveAccessBubbleType bubble_type = GetExclusiveAccessBubbleType(); - - switch (GetMouseLockSetting(web_contents->GetURL())) { - case CONTENT_SETTING_ALLOW: - // If bubble already displaying buttons we must not lock the mouse yet, - // or it would prevent pressing those buttons. Instead, merge the request. - if (!IsPrivilegedFullscreenForTab() && - exclusive_access_bubble::ShowButtonsForType(bubble_type)) { - mouse_lock_state_ = MOUSELOCK_REQUESTED; - } else { - // Lock mouse. - if (web_contents->GotResponseToLockMouseRequest(true)) { - if (last_unlocked_by_target) { - mouse_lock_state_ = MOUSELOCK_ACCEPTED_SILENTLY; - } else { - mouse_lock_state_ = MOUSELOCK_ACCEPTED; - } - } else { - SetMouseLockTab(NULL); - mouse_lock_state_ = MOUSELOCK_NOT_REQUESTED; - } - } - break; - case CONTENT_SETTING_BLOCK: - web_contents->GotResponseToLockMouseRequest(false); - SetMouseLockTab(NULL); - mouse_lock_state_ = MOUSELOCK_NOT_REQUESTED; - break; - case CONTENT_SETTING_ASK: - mouse_lock_state_ = MOUSELOCK_REQUESTED; - break; - default: - NOTREACHED(); - } - UpdateFullscreenExitBubbleContent(); -} - -void FullscreenController::OnTabDeactivated(WebContents* web_contents) { - if (web_contents == fullscreened_tab_ || web_contents == mouse_lock_tab_) - ExitTabFullscreenOrMouseLockIfNecessary(); -} - void FullscreenController::OnTabDetachedFromView(WebContents* old_contents) { if (!IsFullscreenForCapturedTab(old_contents)) return; @@ -327,97 +271,63 @@ void FullscreenController::OnTabClosing(WebContents* web_contents) { if (IsFullscreenForCapturedTab(web_contents)) { web_contents->ExitFullscreen(); - } else if (web_contents == fullscreened_tab_ || - web_contents == mouse_lock_tab_) { - ExitTabFullscreenOrMouseLockIfNecessary(); - // The call to exit fullscreen may result in asynchronous notification of - // fullscreen state change (e.g., on Linux). We don't want to rely on it - // to call NotifyTabOfExitIfNecessary(), because at that point - // |fullscreened_tab_| may not be valid. Instead, we call it here to clean - // up tab fullscreen related state. - NotifyTabOfExitIfNecessary(); + } else { + ExclusiveAccessControllerBase::OnTabClosing(web_contents); } } void FullscreenController::WindowFullscreenStateChanged() { reentrant_window_state_change_call_check_ = true; - bool exiting_fullscreen = !window_->IsFullscreen(); + BrowserWindow* const window = browser()->window(); + bool exiting_fullscreen = !window->IsFullscreen(); PostFullscreenChangeNotification(!exiting_fullscreen); if (exiting_fullscreen) { toggled_into_fullscreen_ = false; extension_caused_fullscreen_ = GURL(); - NotifyTabOfExitIfNecessary(); + NotifyTabExclusiveAccessLost(); } if (exiting_fullscreen) { - window_->GetDownloadShelf()->Unhide(); + window->GetDownloadShelf()->Unhide(); } else { - window_->GetDownloadShelf()->Hide(); - if (window_->GetStatusBubble()) - window_->GetStatusBubble()->Hide(); + window->GetDownloadShelf()->Hide(); + if (window->GetStatusBubble()) + window->GetStatusBubble()->Hide(); } } bool FullscreenController::HandleUserPressedEscape() { WebContents* const active_web_contents = - browser_->tab_strip_model()->GetActiveWebContents(); + browser()->tab_strip_model()->GetActiveWebContents(); if (IsFullscreenForCapturedTab(active_web_contents)) { active_web_contents->ExitFullscreen(); return true; - } else if (IsWindowFullscreenForTabOrPending() || - IsMouseLocked() || IsMouseLockRequested()) { - ExitTabFullscreenOrMouseLockIfNecessary(); + } else if (IsWindowFullscreenForTabOrPending()) { + ExitExclusiveAccessIfNecessary(); return true; } return false; } -void FullscreenController::ExitTabOrBrowserFullscreenToPreviousState() { +void FullscreenController::ExitExclusiveAccessToPreviousState() { if (IsWindowFullscreenForTabOrPending()) - ExitTabFullscreenOrMouseLockIfNecessary(); + ExitFullscreenModeForTab(exclusive_access_tab()); else if (IsFullscreenForBrowser()) ExitFullscreenModeInternal(); } -void FullscreenController::OnAcceptFullscreenPermission() { - ExclusiveAccessBubbleType bubble_type = GetExclusiveAccessBubbleType(); - bool mouse_lock = false; +bool FullscreenController::OnAcceptExclusiveAccessPermission() { + ExclusiveAccessBubbleType bubble_type = + exclusive_access_manager()->GetExclusiveAccessExitBubbleType(); bool fullscreen = false; exclusive_access_bubble::PermissionRequestedByType(bubble_type, &fullscreen, - &mouse_lock); + nullptr); DCHECK(!(fullscreen && tab_fullscreen_accepted_)); - DCHECK(!(mouse_lock && IsMouseLocked())); - - HostContentSettingsMap* settings_map = profile_->GetHostContentSettingsMap(); - - if (mouse_lock && !IsMouseLocked()) { - DCHECK(IsMouseLockRequested()); - - GURL url = GetFullscreenExitBubbleURL(); - ContentSettingsPattern pattern = ContentSettingsPattern::FromURL(url); - - // TODO(markusheintz): We should allow patterns for all possible URLs here. - if (pattern.IsValid()) { - settings_map->SetContentSetting( - pattern, ContentSettingsPattern::Wildcard(), - CONTENT_SETTINGS_TYPE_MOUSELOCK, std::string(), - CONTENT_SETTING_ALLOW); - } - - if (mouse_lock_tab_ && - mouse_lock_tab_->GotResponseToLockMouseRequest(true)) { - mouse_lock_state_ = MOUSELOCK_ACCEPTED; - } else { - mouse_lock_state_ = MOUSELOCK_NOT_REQUESTED; - SetMouseLockTab(NULL); - } - NotifyMouseLockChange(); - } if (fullscreen && !tab_fullscreen_accepted_) { - DCHECK(fullscreened_tab_); + DCHECK(exclusive_access_tab()); // Origins can enter fullscreen even when embedded in other origins. // Permission is tracked based on the combinations of requester and // embedder. Thus, even if a requesting origin has been previously approved @@ -438,112 +348,39 @@ // ContentSettings requires valid patterns and the patterns might be invalid // in some edge cases like if the current frame is about:blank. if (primary_pattern.IsValid() && secondary_pattern.IsValid()) { + HostContentSettingsMap* settings_map = + profile()->GetHostContentSettingsMap(); settings_map->SetContentSetting( primary_pattern, secondary_pattern, CONTENT_SETTINGS_TYPE_FULLSCREEN, std::string(), CONTENT_SETTING_ALLOW); } tab_fullscreen_accepted_ = true; - } - UpdateFullscreenExitBubbleContent(); -} - -void FullscreenController::OnDenyFullscreenPermission() { - if (!fullscreened_tab_ && !mouse_lock_tab_) - return; - - if (IsMouseLockRequested()) { - mouse_lock_state_ = MOUSELOCK_NOT_REQUESTED; - if (mouse_lock_tab_) - mouse_lock_tab_->GotResponseToLockMouseRequest(false); - SetMouseLockTab(NULL); - NotifyMouseLockChange(); - - // UpdateFullscreenExitBubbleContent() must be called, but to avoid - // duplicate calls we do so only if not adjusting the fullscreen state - // below, which also calls UpdateFullscreenExitBubbleContent(). - if (!IsWindowFullscreenForTabOrPending()) - UpdateFullscreenExitBubbleContent(); + return true; } - if (IsWindowFullscreenForTabOrPending()) - ExitTabFullscreenOrMouseLockIfNecessary(); + return false; } -void FullscreenController::LostMouseLock() { - mouse_lock_state_ = MOUSELOCK_NOT_REQUESTED; - SetMouseLockTab(NULL); - NotifyMouseLockChange(); - UpdateFullscreenExitBubbleContent(); +bool FullscreenController::OnDenyExclusiveAccessPermission() { + if (IsWindowFullscreenForTabOrPending()) { + ExitExclusiveAccessIfNecessary(); + return true; + } + + return false; } -void FullscreenController::Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) { - DCHECK_EQ(content::NOTIFICATION_NAV_ENTRY_COMMITTED, type); - if (content::Details<content::LoadCommittedDetails>(details)-> - is_navigation_to_different_page()) - ExitTabFullscreenOrMouseLockIfNecessary(); -} - -GURL FullscreenController::GetFullscreenExitBubbleURL() const { - if (fullscreened_tab_) +GURL FullscreenController::GetURLForExclusiveAccessBubble() const { + if (exclusive_access_tab()) return GetRequestingOrigin(); - if (mouse_lock_tab_) - return mouse_lock_tab_->GetURL(); return extension_caused_fullscreen_; } -ExclusiveAccessBubbleType FullscreenController::GetExclusiveAccessBubbleType() - const { - // In kiosk and exclusive app mode we always want to be fullscreen and do not - // want to show exit instructions for browser mode fullscreen. - bool app_mode = false; -#if !defined(OS_MACOSX) // App mode (kiosk) is not available on Mac yet. - app_mode = chrome::IsRunningInAppMode(); -#endif - - if (mouse_lock_state_ == MOUSELOCK_ACCEPTED_SILENTLY) - return EXCLUSIVE_ACCESS_BUBBLE_TYPE_NONE; - - if (!fullscreened_tab_) { - if (IsMouseLocked()) - return EXCLUSIVE_ACCESS_BUBBLE_TYPE_MOUSELOCK_EXIT_INSTRUCTION; - if (IsMouseLockRequested()) - return EXCLUSIVE_ACCESS_BUBBLE_TYPE_MOUSELOCK_BUTTONS; - if (!extension_caused_fullscreen_.is_empty()) - return EXCLUSIVE_ACCESS_BUBBLE_TYPE_EXTENSION_FULLSCREEN_EXIT_INSTRUCTION; - if (toggled_into_fullscreen_ && !app_mode) - return EXCLUSIVE_ACCESS_BUBBLE_TYPE_BROWSER_FULLSCREEN_EXIT_INSTRUCTION; - return EXCLUSIVE_ACCESS_BUBBLE_TYPE_NONE; - } - - if (tab_fullscreen_accepted_) { - if (IsPrivilegedFullscreenForTab()) - return EXCLUSIVE_ACCESS_BUBBLE_TYPE_NONE; - if (IsMouseLocked()) - return EXCLUSIVE_ACCESS_BUBBLE_TYPE_FULLSCREEN_MOUSELOCK_EXIT_INSTRUCTION; - if (IsMouseLockRequested()) - return EXCLUSIVE_ACCESS_BUBBLE_TYPE_MOUSELOCK_BUTTONS; - return EXCLUSIVE_ACCESS_BUBBLE_TYPE_FULLSCREEN_EXIT_INSTRUCTION; - } - - if (IsMouseLockRequested()) - return EXCLUSIVE_ACCESS_BUBBLE_TYPE_FULLSCREEN_MOUSELOCK_BUTTONS; - return EXCLUSIVE_ACCESS_BUBBLE_TYPE_FULLSCREEN_BUTTONS; -} - -void FullscreenController::UpdateNotificationRegistrations() { - if (fullscreened_tab_ && mouse_lock_tab_) - DCHECK(fullscreened_tab_ == mouse_lock_tab_); - - WebContents* tab = fullscreened_tab_ ? fullscreened_tab_ : mouse_lock_tab_; - - if (tab && registrar_.IsEmpty()) { - registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, - content::Source<content::NavigationController>(&tab->GetController())); - } else if (!tab && !registrar_.IsEmpty()) { - registrar_.RemoveAll(); - } +void FullscreenController::ExitExclusiveAccessIfNecessary() { + if (IsWindowFullscreenForTabOrPending()) + ExitFullscreenModeForTab(exclusive_access_tab()); + else + NotifyTabExclusiveAccessLost(); } void FullscreenController::PostFullscreenChangeNotification( @@ -562,35 +399,16 @@ content::Details<bool>(&is_fullscreen)); } -void FullscreenController::NotifyTabOfExitIfNecessary() { - if (fullscreened_tab_) { - WebContents* web_contents = fullscreened_tab_; - // This call will set |fullscreened_tab_| to nullptr. - SetFullscreenedTab(nullptr, GURL()); +void FullscreenController::NotifyTabExclusiveAccessLost() { + if (exclusive_access_tab()) { + WebContents* web_contents = exclusive_access_tab(); + SetTabWithExclusiveAccess(nullptr); + fullscreened_origin_ = GURL(); state_prior_to_tab_fullscreen_ = STATE_INVALID; tab_fullscreen_accepted_ = false; web_contents->ExitFullscreen(); + exclusive_access_manager()->UpdateExclusiveAccessExitBubbleContent(); } - - if (mouse_lock_tab_) { - if (IsMouseLockRequested()) { - mouse_lock_tab_->GotResponseToLockMouseRequest(false); - NotifyMouseLockChange(); - } else { - UnlockMouse(); - } - SetMouseLockTab(NULL); - mouse_lock_state_ = MOUSELOCK_NOT_REQUESTED; - } - - UpdateFullscreenExitBubbleContent(); -} - -void FullscreenController::NotifyMouseLockChange() { - content::NotificationService::current()->Notify( - chrome::NOTIFICATION_MOUSE_LOCK_CHANGED, - content::Source<FullscreenController>(this), - content::NotificationService::NoDetails()); } void FullscreenController::ToggleFullscreenModeInternal( @@ -601,24 +419,23 @@ return; #endif - bool enter_fullscreen = !window_->IsFullscreen(); + BrowserWindow* const window = browser()->window(); + bool enter_fullscreen = !window->IsFullscreen(); // When a Mac user requests a toggle they may be toggling between // FullscreenWithoutChrome and FullscreenWithToolbar. - if (window_->IsFullscreen() && - !IsWindowFullscreenForTabOrPending() && - window_->SupportsFullscreenWithToolbar()) { + if (window->IsFullscreen() && !IsWindowFullscreenForTabOrPending() && + window->SupportsFullscreenWithToolbar()) { if (option == BROWSER_WITH_TOOLBAR) { - enter_fullscreen = - enter_fullscreen || !window_->IsFullscreenWithToolbar(); + enter_fullscreen = enter_fullscreen || !window->IsFullscreenWithToolbar(); } else { - enter_fullscreen = enter_fullscreen || window_->IsFullscreenWithToolbar(); + enter_fullscreen = enter_fullscreen || window->IsFullscreenWithToolbar(); } } // In kiosk mode, we always want to be fullscreen. When the browser first // starts we're not yet fullscreen, so let the initial toggle go through. - if (chrome::IsRunningInAppMode() && window_->IsFullscreen()) + if (chrome::IsRunningInAppMode() && window->IsFullscreen()) return; #if !defined(OS_MACOSX) @@ -626,7 +443,7 @@ // from manually entering fullscreen mode and also disables kiosk mode on // desktop platforms. if (enter_fullscreen && - !profile_->GetPrefs()->GetBoolean(prefs::kFullscreenAllowed)) { + !profile()->GetPrefs()->GetBoolean(prefs::kFullscreenAllowed)) { return; } #endif @@ -654,10 +471,11 @@ // TODO(scheib): Record metrics for WITH_TOOLBAR, without counting transitions // from tab fullscreen out to browser with toolbar. - window_->EnterFullscreen(url, GetExclusiveAccessBubbleType(), - option == BROWSER_WITH_TOOLBAR); + browser()->window()->EnterFullscreen( + url, exclusive_access_manager()->GetExclusiveAccessExitBubbleType(), + option == BROWSER_WITH_TOOLBAR); - UpdateFullscreenExitBubbleContent(); + exclusive_access_manager()->UpdateExclusiveAccessExitBubbleContent(); // Once the window has become fullscreen it'll call back to // WindowFullscreenStateChanged(). We don't do this immediately as @@ -671,47 +489,16 @@ // Mac windows report a state change instantly, and so we must also clear // state_prior_to_tab_fullscreen_ to match them else other logic using // state_prior_to_tab_fullscreen_ will be incorrect. - NotifyTabOfExitIfNecessary(); + NotifyTabExclusiveAccessLost(); #endif - window_->ExitFullscreen(); + browser()->window()->ExitFullscreen(); extension_caused_fullscreen_ = GURL(); - UpdateFullscreenExitBubbleContent(); -} - -void FullscreenController::SetFullscreenedTab(WebContents* tab, - const GURL& origin) { - fullscreened_tab_ = tab; - fullscreened_origin_ = origin; - UpdateNotificationRegistrations(); -} - -void FullscreenController::SetMouseLockTab(WebContents* tab) { - mouse_lock_tab_ = tab; - UpdateNotificationRegistrations(); -} - -void FullscreenController::ExitTabFullscreenOrMouseLockIfNecessary() { - if (IsWindowFullscreenForTabOrPending()) - ExitFullscreenModeForTab(fullscreened_tab_); - else - NotifyTabOfExitIfNecessary(); -} - -void FullscreenController::UpdateFullscreenExitBubbleContent() { - GURL url = GetFullscreenExitBubbleURL(); - ExclusiveAccessBubbleType bubble_type = GetExclusiveAccessBubbleType(); - - // If bubble displays buttons, unlock mouse to allow pressing them. - if (exclusive_access_bubble::ShowButtonsForType(bubble_type) && - IsMouseLocked()) - UnlockMouse(); - - window_->UpdateFullscreenExitBubbleContent(url, bubble_type); + exclusive_access_manager()->UpdateExclusiveAccessExitBubbleContent(); } ContentSetting FullscreenController::GetFullscreenSetting() const { - DCHECK(fullscreened_tab_); + DCHECK(exclusive_access_tab()); GURL url = GetRequestingOrigin(); @@ -720,7 +507,7 @@ // If the permission was granted to the website with no embedder, it should // always be allowed, even if embedded. - if (profile_->GetHostContentSettingsMap()->GetContentSetting( + if (profile()->GetHostContentSettingsMap()->GetContentSetting( url, url, CONTENT_SETTINGS_TYPE_FULLSCREEN, std::string()) == CONTENT_SETTING_ALLOW) { return CONTENT_SETTING_ALLOW; @@ -728,25 +515,15 @@ // See the comment above the call to |SetContentSetting()| for how the // requesting and embedding origins interact with each other wrt permissions. - return profile_->GetHostContentSettingsMap()->GetContentSetting( + return profile()->GetHostContentSettingsMap()->GetContentSetting( url, GetEmbeddingOrigin(), CONTENT_SETTINGS_TYPE_FULLSCREEN, std::string()); } -ContentSetting -FullscreenController::GetMouseLockSetting(const GURL& url) const { - if (IsPrivilegedFullscreenForTab() || url.SchemeIsFile()) - return CONTENT_SETTING_ALLOW; - - HostContentSettingsMap* settings_map = profile_->GetHostContentSettingsMap(); - return settings_map->GetContentSetting(url, url, - CONTENT_SETTINGS_TYPE_MOUSELOCK, std::string()); -} - bool FullscreenController::IsPrivilegedFullscreenForTab() const { const bool embedded_widget_present = - fullscreened_tab_ && - fullscreened_tab_->GetFullscreenRenderWidgetHostView(); + exclusive_access_tab() && + exclusive_access_tab()->GetFullscreenRenderWidgetHostView(); return embedded_widget_present || is_privileged_fullscreen_for_testing_; } @@ -776,43 +553,30 @@ bool FullscreenController::IsFullscreenForCapturedTab( const WebContents* web_contents) const { - // Note: On Mac, some of the OnTabXXX() methods get called with a NULL value + // Note: On Mac, some of the OnTabXXX() methods get called with a nullptr + // value // for web_contents. Check for that here. - const FullscreenWithinTabHelper* const helper = web_contents ? - FullscreenWithinTabHelper::FromWebContents(web_contents) : NULL; + const FullscreenWithinTabHelper* const helper = + web_contents ? FullscreenWithinTabHelper::FromWebContents(web_contents) + : nullptr; if (helper && helper->is_fullscreen_for_captured_tab()) { - DCHECK_NE(fullscreened_tab_, web_contents); + DCHECK_NE(exclusive_access_tab(), web_contents); return true; } return false; } -void FullscreenController::UnlockMouse() { - if (!mouse_lock_tab_) - return; - content::RenderWidgetHostView* mouse_lock_view = - (fullscreened_tab_ == mouse_lock_tab_ && IsPrivilegedFullscreenForTab()) ? - mouse_lock_tab_->GetFullscreenRenderWidgetHostView() : NULL; - if (!mouse_lock_view) { - RenderViewHost* const rvh = mouse_lock_tab_->GetRenderViewHost(); - if (rvh) - mouse_lock_view = rvh->GetView(); - } - if (mouse_lock_view) - mouse_lock_view->UnlockMouse(); -} - GURL FullscreenController::GetRequestingOrigin() const { - DCHECK(fullscreened_tab_); + DCHECK(exclusive_access_tab()); if (!fullscreened_origin_.is_empty()) return fullscreened_origin_; - return fullscreened_tab_->GetLastCommittedURL(); + return exclusive_access_tab()->GetLastCommittedURL(); } GURL FullscreenController::GetEmbeddingOrigin() const { - DCHECK(fullscreened_tab_); + DCHECK(exclusive_access_tab()); - return fullscreened_tab_->GetLastCommittedURL(); + return exclusive_access_tab()->GetLastCommittedURL(); }
diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller.h b/chrome/browser/ui/exclusive_access/fullscreen_controller.h index d276678..763591f 100644 --- a/chrome/browser/ui/exclusive_access/fullscreen_controller.h +++ b/chrome/browser/ui/exclusive_access/fullscreen_controller.h
@@ -9,15 +9,12 @@ #include "base/basictypes.h" #include "base/memory/weak_ptr.h" -#include "chrome/browser/ui/exclusive_access/exclusive_access_bubble_type.h" +#include "chrome/browser/ui/exclusive_access/exclusive_access_controller_base.h" #include "components/content_settings/core/common/content_settings.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" -class Browser; -class BrowserWindow; class GURL; -class Profile; namespace content { class WebContents; @@ -34,8 +31,7 @@ // tab so it can stop rendering in its fullscreen mode. // // For Flash, FullscreenController will auto-accept all permission requests for -// fullscreen and/or mouse lock, since the assumption is that the plugin handles -// this for us. +// fullscreen, since the assumption is that the plugin handles this for us. // // FullscreenWithinTab Note: // All fullscreen widgets are displayed within the tab contents area, and @@ -50,10 +46,10 @@ // quality improvement since scaling and letterboxing steps can be skipped in // the capture pipeline. -// This class implements fullscreen and mouselock behaviour. -class FullscreenController : public content::NotificationObserver { +// This class implements fullscreen behaviour. +class FullscreenController : public ExclusiveAccessControllerBase { public: - explicit FullscreenController(Browser* browser); + FullscreenController(ExclusiveAccessManager* manager, Browser* browser); ~FullscreenController() override; // Browser/User Fullscreen /////////////////////////////////////////////////// @@ -63,6 +59,9 @@ // transition. bool IsFullscreenForBrowser() const; + // Returns true if Flash is providing the "exit from fullscreen" message. + bool IsPrivilegedFullscreenForTab() const; + void ToggleBrowserFullscreenMode(); // Fullscreen mode with tab strip and toolbar shown. @@ -81,6 +80,16 @@ // BrowserWindow::IsFullscreen() may still return false. bool IsWindowFullscreenForTabOrPending() const; + // Returns true if the browser window is fullscreen because of extension + // initiated fullscreen. + bool IsExtensionFullscreenOrPending() const; + + // Returns true if controller has entered fullscreen mode. + bool IsControllerInitiatedFullscreen() const; + + // Returns true if the user has accepted fullscreen. + bool IsUserAcceptedFullscreen() const; + // Returns true if the tab is/will be in fullscreen mode. Note: This does NOT // indicate whether the browser window is/will be fullscreened as well. See // 'FullscreenWithinTab Note'. @@ -116,95 +125,46 @@ void SetMetroSnapMode(bool enable); #endif - // Mouse Lock //////////////////////////////////////////////////////////////// + // Overrde from ExclusiveAccessControllerBase. + void OnTabDetachedFromView(content::WebContents* web_contents) override; + void OnTabClosing(content::WebContents* web_contents) override; + bool HandleUserPressedEscape() override; - bool IsMouseLockRequested() const; - bool IsMouseLocked() const; - - void RequestToLockMouse(content::WebContents* web_contents, - bool user_gesture, - bool last_unlocked_by_target); - + void ExitExclusiveAccessToPreviousState() override; + bool OnAcceptExclusiveAccessPermission() override; + bool OnDenyExclusiveAccessPermission() override; + GURL GetURLForExclusiveAccessBubble() const override; + void ExitExclusiveAccessIfNecessary() override; // Callbacks ///////////////////////////////////////////////////////////////// - // Called by Browser::TabDeactivated. - void OnTabDeactivated(content::WebContents* web_contents); - - // Called by Browser::ActiveTabChanged. - void OnTabDetachedFromView(content::WebContents* web_contents); - - // Called by Browser::TabClosingAt. - void OnTabClosing(content::WebContents* web_contents); - // Called by Browser::WindowFullscreenStateChanged. void WindowFullscreenStateChanged(); - // Called by Browser::PreHandleKeyboardEvent. - bool HandleUserPressedEscape(); - - // Called by platform FullscreenExitBubble. - void ExitTabOrBrowserFullscreenToPreviousState(); - void OnAcceptFullscreenPermission(); - void OnDenyFullscreenPermission(); - - // Called by Browser::LostMouseLock. - void LostMouseLock(); - - // content::NotificationObserver: - void Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) override; - - // Bubble Content //////////////////////////////////////////////////////////// - - GURL GetFullscreenExitBubbleURL() const; - ExclusiveAccessBubbleType GetExclusiveAccessBubbleType() const; - private: friend class FullscreenControllerTest; - enum MouseLockState { - MOUSELOCK_NOT_REQUESTED, - // The page requests to lock the mouse and the user hasn't responded to the - // request. - MOUSELOCK_REQUESTED, - // Mouse lock has been allowed by the user. - MOUSELOCK_ACCEPTED, - // Mouse lock has been silently accepted, no notification to user. - MOUSELOCK_ACCEPTED_SILENTLY - }; - enum FullscreenInternalOption { BROWSER, BROWSER_WITH_TOOLBAR, TAB }; - void UpdateNotificationRegistrations(); - // Posts a task to call NotifyFullscreenChange. void PostFullscreenChangeNotification(bool is_fullscreen); // Sends a NOTIFICATION_FULLSCREEN_CHANGED notification. void NotifyFullscreenChange(bool is_fullscreen); - // Notifies the tab that it has been forced out of fullscreen and mouse lock - // mode if necessary. - void NotifyTabOfExitIfNecessary(); - void NotifyMouseLockChange(); + + // Notifies the tab that it has been forced out of fullscreen mode if + // necessary. + void NotifyTabExclusiveAccessLost() override; void ToggleFullscreenModeInternal(FullscreenInternalOption option); void EnterFullscreenModeInternal(FullscreenInternalOption option); void ExitFullscreenModeInternal(); void SetFullscreenedTab(content::WebContents* tab, const GURL& origin); - void SetMouseLockTab(content::WebContents* tab); - - // Make the current tab exit fullscreen mode or mouse lock if it is in it. - void ExitTabFullscreenOrMouseLockIfNecessary(); - void UpdateFullscreenExitBubbleContent(); ContentSetting GetFullscreenSetting() const; - ContentSetting GetMouseLockSetting(const GURL& url) const; - bool IsPrivilegedFullscreenForTab() const; void SetPrivilegedFullscreenForTesting(bool is_privileged); // Returns true if |web_contents| was toggled into/out of fullscreen mode as a // screen-captured tab. See 'FullscreenWithinTab Note'. @@ -214,21 +174,11 @@ // tab. See 'FullscreenWithinTab Note'. bool IsFullscreenForCapturedTab(const content::WebContents* web_contents) const; - void UnlockMouse(); // Helper methods that should be used in a TAB context. GURL GetRequestingOrigin() const; GURL GetEmbeddingOrigin() const; - Browser* const browser_; - BrowserWindow* const window_; - Profile* const profile_; - - // If there is currently a tab in fullscreen mode (entered via - // webkitRequestFullScreen), this is its WebContents. - // Assign using SetFullscreenedTab(). - content::WebContents* fullscreened_tab_; - // If a tab is fullscreen, the |fullscreen_origin_| should be used as the // origin with regards to fullscreen. The |fullscreened_tab_| url should be // used as the embedder url. @@ -253,14 +203,6 @@ // True if this controller has toggled into tab OR browser fullscreen. bool toggled_into_fullscreen_; - // WebContents for current tab requesting or currently in mouse lock. - // Assign using SetMouseLockTab(). - content::WebContents* mouse_lock_tab_; - - MouseLockState mouse_lock_state_; - - content::NotificationRegistrar registrar_; - // Used to verify that calls we expect to reenter by calling // WindowFullscreenStateChanged do so. bool reentrant_window_state_change_call_check_;
diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller_state_test.cc b/chrome/browser/ui/exclusive_access/fullscreen_controller_state_test.cc index 189b654..0a6fbc5 100644 --- a/chrome/browser/ui/exclusive_access/fullscreen_controller_state_test.cc +++ b/chrome/browser/ui/exclusive_access/fullscreen_controller_state_test.cc
@@ -415,15 +415,19 @@ break; case BUBBLE_EXIT_LINK: - GetFullscreenController()->ExitTabOrBrowserFullscreenToPreviousState(); + GetFullscreenController()->ExitExclusiveAccessToPreviousState(); break; case BUBBLE_ALLOW: - GetFullscreenController()->OnAcceptFullscreenPermission(); + GetBrowser() + ->exclusive_access_manager() + ->OnAcceptExclusiveAccessPermission(); break; case BUBBLE_DENY: - GetFullscreenController()->OnDenyFullscreenPermission(); + GetBrowser() + ->exclusive_access_manager() + ->OnDenyExclusiveAccessPermission(); break; case WINDOW_CHANGE: @@ -756,7 +760,7 @@ } FullscreenController* FullscreenControllerStateTest::GetFullscreenController() { - return GetBrowser()->fullscreen_controller(); + return GetBrowser()->exclusive_access_manager()->fullscreen_controller(); } std::string FullscreenControllerStateTest::GetTransitionTableAsString() const {
diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller_state_unittest.cc b/chrome/browser/ui/exclusive_access/fullscreen_controller_state_unittest.cc index 541a8b5..31ef252 100644 --- a/chrome/browser/ui/exclusive_access/fullscreen_controller_state_unittest.cc +++ b/chrome/browser/ui/exclusive_access/fullscreen_controller_state_unittest.cc
@@ -428,7 +428,9 @@ browser()->window()->ExitFullscreen(); ChangeWindowFullscreenState(); EXPECT_EQ(EXCLUSIVE_ACCESS_BUBBLE_TYPE_NONE, - browser()->fullscreen_controller()->GetExclusiveAccessBubbleType()); + browser() + ->exclusive_access_manager() + ->GetExclusiveAccessExitBubbleType()); } // Test that switching tabs takes the browser out of tab fullscreen. @@ -763,8 +765,9 @@ EXPECT_TRUE(wc_delegate->IsFullscreenForTabOrPending(tab)); EXPECT_TRUE(second_wc_delegate->IsFullscreenForTabOrPending(tab)); EXPECT_FALSE(GetFullscreenController()->IsWindowFullscreenForTabOrPending()); - EXPECT_FALSE(second_browser->fullscreen_controller()-> - IsWindowFullscreenForTabOrPending()); + EXPECT_FALSE(second_browser->exclusive_access_manager() + ->fullscreen_controller() + ->IsWindowFullscreenForTabOrPending()); // Now, detach and reattach it back to the first browser window. Again, the // tab should remain in fullscreen mode and neither browser window should have @@ -777,8 +780,9 @@ EXPECT_TRUE(wc_delegate->IsFullscreenForTabOrPending(tab)); EXPECT_TRUE(second_wc_delegate->IsFullscreenForTabOrPending(tab)); EXPECT_FALSE(GetFullscreenController()->IsWindowFullscreenForTabOrPending()); - EXPECT_FALSE(second_browser->fullscreen_controller()-> - IsWindowFullscreenForTabOrPending()); + EXPECT_FALSE(second_browser->exclusive_access_manager() + ->fullscreen_controller() + ->IsWindowFullscreenForTabOrPending()); // Exit fullscreen. ASSERT_TRUE(InvokeEvent(TAB_FULLSCREEN_FALSE)); @@ -786,8 +790,9 @@ EXPECT_FALSE(wc_delegate->IsFullscreenForTabOrPending(tab)); EXPECT_FALSE(second_wc_delegate->IsFullscreenForTabOrPending(tab)); EXPECT_FALSE(GetFullscreenController()->IsWindowFullscreenForTabOrPending()); - EXPECT_FALSE(second_browser->fullscreen_controller()-> - IsWindowFullscreenForTabOrPending()); + EXPECT_FALSE(second_browser->exclusive_access_manager() + ->fullscreen_controller() + ->IsWindowFullscreenForTabOrPending()); // Required tear-down specific to this test. second_browser->tab_strip_model()->CloseAllTabs();
diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller_test.cc b/chrome/browser/ui/exclusive_access/fullscreen_controller_test.cc index bf1925f1..335892b 100644 --- a/chrome/browser/ui/exclusive_access/fullscreen_controller_test.cc +++ b/chrome/browser/ui/exclusive_access/fullscreen_controller_test.cc
@@ -27,34 +27,39 @@ last_unlocked_by_target); } +FullscreenController* FullscreenControllerTest::GetFullscreenController() { + return GetExclusiveAccessManager()->fullscreen_controller(); +} + +ExclusiveAccessManager* FullscreenControllerTest::GetExclusiveAccessManager() { + return browser()->exclusive_access_manager(); +} + void FullscreenControllerTest::LostMouseLock() { browser()->LostMouseLock(); } bool FullscreenControllerTest::SendEscapeToFullscreenController() { - return browser()->fullscreen_controller()->HandleUserPressedEscape(); + return GetExclusiveAccessManager()->HandleUserPressedEscape(); } bool FullscreenControllerTest::IsFullscreenForBrowser() { - return browser()->fullscreen_controller()->IsFullscreenForBrowser(); + return GetFullscreenController()->IsFullscreenForBrowser(); } bool FullscreenControllerTest::IsWindowFullscreenForTabOrPending() { - return browser()->fullscreen_controller()-> - IsWindowFullscreenForTabOrPending(); + return GetFullscreenController()->IsWindowFullscreenForTabOrPending(); } bool FullscreenControllerTest::IsMouseLockPermissionRequested() { - ExclusiveAccessBubbleType type = - browser()->fullscreen_controller()->GetExclusiveAccessBubbleType(); + ExclusiveAccessBubbleType type = GetExclusiveAccessBubbleType(); bool mouse_lock = false; exclusive_access_bubble::PermissionRequestedByType(type, NULL, &mouse_lock); return mouse_lock; } bool FullscreenControllerTest::IsFullscreenPermissionRequested() { - ExclusiveAccessBubbleType type = - browser()->fullscreen_controller()->GetExclusiveAccessBubbleType(); + ExclusiveAccessBubbleType type = GetExclusiveAccessBubbleType(); bool fullscreen = false; exclusive_access_bubble::PermissionRequestedByType(type, &fullscreen, NULL); return fullscreen; @@ -62,27 +67,24 @@ ExclusiveAccessBubbleType FullscreenControllerTest::GetExclusiveAccessBubbleType() { - return browser()->fullscreen_controller()->GetExclusiveAccessBubbleType(); + return GetExclusiveAccessManager()->GetExclusiveAccessExitBubbleType(); } bool FullscreenControllerTest::IsFullscreenBubbleDisplayed() { - ExclusiveAccessBubbleType type = - browser()->fullscreen_controller()->GetExclusiveAccessBubbleType(); - return type != EXCLUSIVE_ACCESS_BUBBLE_TYPE_NONE; + return GetExclusiveAccessBubbleType() != EXCLUSIVE_ACCESS_BUBBLE_TYPE_NONE; } bool FullscreenControllerTest::IsFullscreenBubbleDisplayingButtons() { - ExclusiveAccessBubbleType type = - browser()->fullscreen_controller()->GetExclusiveAccessBubbleType(); - return exclusive_access_bubble::ShowButtonsForType(type); + return exclusive_access_bubble::ShowButtonsForType( + GetExclusiveAccessBubbleType()); } void FullscreenControllerTest::AcceptCurrentFullscreenOrMouseLockRequest() { - browser()->fullscreen_controller()->OnAcceptFullscreenPermission(); + GetExclusiveAccessManager()->OnAcceptExclusiveAccessPermission(); } void FullscreenControllerTest::DenyCurrentFullscreenOrMouseLockRequest() { - browser()->fullscreen_controller()->OnDenyFullscreenPermission(); + GetExclusiveAccessManager()->OnDenyExclusiveAccessPermission(); } void FullscreenControllerTest::GoBack() { @@ -100,6 +102,5 @@ } void FullscreenControllerTest::SetPrivilegedFullscreen(bool is_privileged) { - browser()->fullscreen_controller()-> - SetPrivilegedFullscreenForTesting(is_privileged); + GetFullscreenController()->SetPrivilegedFullscreenForTesting(is_privileged); }
diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller_test.h b/chrome/browser/ui/exclusive_access/fullscreen_controller_test.h index 59928b2d..039a016 100644 --- a/chrome/browser/ui/exclusive_access/fullscreen_controller_test.h +++ b/chrome/browser/ui/exclusive_access/fullscreen_controller_test.h
@@ -7,6 +7,7 @@ #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_bubble_type.h" +#include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" #include "chrome/test/base/in_process_browser_test.h" #include "content/public/browser/notification_service.h" #include "content/public/test/test_utils.h" @@ -55,6 +56,9 @@ void Reload(); void SetPrivilegedFullscreen(bool is_privileged); static const char kFullscreenMouseLockHTML[]; + FullscreenController* GetFullscreenController(); + ExclusiveAccessManager* GetExclusiveAccessManager(); + private: void ToggleTabFullscreen_Internal(bool enter_fullscreen, bool retry_until_success);
diff --git a/chrome/browser/ui/exclusive_access/mouse_lock_controller.cc b/chrome/browser/ui/exclusive_access/mouse_lock_controller.cc new file mode 100644 index 0000000..a053b85 --- /dev/null +++ b/chrome/browser/ui/exclusive_access/mouse_lock_controller.cc
@@ -0,0 +1,234 @@ +// Copyright (c) 2015 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/exclusive_access/mouse_lock_controller.h" + +#include "chrome/browser/chrome_notification_types.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" +#include "components/content_settings/core/browser/host_content_settings_map.h" +#include "content/public/browser/notification_service.h" +#include "content/public/browser/render_view_host.h" +#include "content/public/browser/render_widget_host_view.h" +#include "content/public/browser/web_contents.h" + +using content::RenderViewHost; +using content::WebContents; + +MouseLockController::MouseLockController(ExclusiveAccessManager* manager, + Browser* browser) + : ExclusiveAccessControllerBase(manager, browser), + mouse_lock_state_(MOUSELOCK_NOT_REQUESTED) { +} + +MouseLockController::~MouseLockController() { +} + +bool MouseLockController::IsMouseLocked() const { + return mouse_lock_state_ == MOUSELOCK_ACCEPTED || + mouse_lock_state_ == MOUSELOCK_ACCEPTED_SILENTLY; +} + +bool MouseLockController::IsMouseLockSilentlyAccepted() const { + return mouse_lock_state_ == MOUSELOCK_ACCEPTED_SILENTLY; +} + +void MouseLockController::RequestToLockMouse(WebContents* web_contents, + bool user_gesture, + bool last_unlocked_by_target) { + DCHECK(!IsMouseLocked()); + NotifyMouseLockChange(); + + // Must have a user gesture to prevent misbehaving sites from constantly + // re-locking the mouse. Exceptions are when the page has unlocked + // (i.e. not the user), or if we're in tab fullscreen (user gesture required + // for that) + if (!last_unlocked_by_target && !user_gesture && + !exclusive_access_manager() + ->fullscreen_controller() + ->IsFullscreenForTabOrPending(web_contents)) { + web_contents->GotResponseToLockMouseRequest(false); + return; + } + SetTabWithExclusiveAccess(web_contents); + ExclusiveAccessBubbleType bubble_type = + exclusive_access_manager()->GetExclusiveAccessExitBubbleType(); + + switch (GetMouseLockSetting(web_contents->GetURL())) { + case CONTENT_SETTING_ALLOW: + // If bubble already displaying buttons we must not lock the mouse yet, + // or it would prevent pressing those buttons. Instead, merge the request. + if (!exclusive_access_manager() + ->fullscreen_controller() + ->IsPrivilegedFullscreenForTab() && + exclusive_access_bubble::ShowButtonsForType(bubble_type)) { + mouse_lock_state_ = MOUSELOCK_REQUESTED; + } else { + // Lock mouse. + if (web_contents->GotResponseToLockMouseRequest(true)) { + if (last_unlocked_by_target) { + mouse_lock_state_ = MOUSELOCK_ACCEPTED_SILENTLY; + } else { + mouse_lock_state_ = MOUSELOCK_ACCEPTED; + } + } else { + SetTabWithExclusiveAccess(nullptr); + mouse_lock_state_ = MOUSELOCK_NOT_REQUESTED; + } + } + break; + case CONTENT_SETTING_BLOCK: + web_contents->GotResponseToLockMouseRequest(false); + SetTabWithExclusiveAccess(nullptr); + mouse_lock_state_ = MOUSELOCK_NOT_REQUESTED; + break; + case CONTENT_SETTING_ASK: + mouse_lock_state_ = MOUSELOCK_REQUESTED; + break; + default: + NOTREACHED(); + } + exclusive_access_manager()->UpdateExclusiveAccessExitBubbleContent(); +} + +void MouseLockController::ExitExclusiveAccessIfNecessary() { + NotifyTabExclusiveAccessLost(); +} + +void MouseLockController::NotifyTabExclusiveAccessLost() { + WebContents* tab = exclusive_access_tab(); + if (tab) { + if (IsMouseLockRequested()) { + tab->GotResponseToLockMouseRequest(false); + NotifyMouseLockChange(); + } else { + UnlockMouse(); + } + SetTabWithExclusiveAccess(nullptr); + mouse_lock_state_ = MOUSELOCK_NOT_REQUESTED; + exclusive_access_manager()->UpdateExclusiveAccessExitBubbleContent(); + } +} + +bool MouseLockController::HandleUserPressedEscape() { + if (IsMouseLocked() || IsMouseLockRequested()) { + ExitExclusiveAccessIfNecessary(); + return true; + } + + return false; +} + +void MouseLockController::ExitExclusiveAccessToPreviousState() { + // Nothing to do for mouse lock. +} + +bool MouseLockController::OnAcceptExclusiveAccessPermission() { + ExclusiveAccessBubbleType bubble_type = + exclusive_access_manager()->GetExclusiveAccessExitBubbleType(); + bool mouse_lock = false; + exclusive_access_bubble::PermissionRequestedByType(bubble_type, nullptr, + &mouse_lock); + DCHECK(!(mouse_lock && IsMouseLocked())); + + if (mouse_lock && !IsMouseLocked()) { + DCHECK(IsMouseLockRequested()); + + HostContentSettingsMap* settings_map = + profile()->GetHostContentSettingsMap(); + + GURL url = GetExclusiveAccessBubbleURL(); + ContentSettingsPattern pattern = ContentSettingsPattern::FromURL(url); + + // TODO(markusheintz): We should allow patterns for all possible URLs here. + if (pattern.IsValid()) { + settings_map->SetContentSetting(pattern, + ContentSettingsPattern::Wildcard(), + CONTENT_SETTINGS_TYPE_MOUSELOCK, + std::string(), CONTENT_SETTING_ALLOW); + } + + WebContents* tab = exclusive_access_tab(); + if (tab && tab->GotResponseToLockMouseRequest(true)) { + mouse_lock_state_ = MOUSELOCK_ACCEPTED; + } else { + mouse_lock_state_ = MOUSELOCK_NOT_REQUESTED; + SetTabWithExclusiveAccess(nullptr); + } + NotifyMouseLockChange(); + return true; + } + + return false; +} + +bool MouseLockController::OnDenyExclusiveAccessPermission() { + WebContents* tab = exclusive_access_tab(); + + if (tab && IsMouseLockRequested()) { + mouse_lock_state_ = MOUSELOCK_NOT_REQUESTED; + tab->GotResponseToLockMouseRequest(false); + SetTabWithExclusiveAccess(nullptr); + NotifyMouseLockChange(); + return true; + } + + return false; +} + +void MouseLockController::LostMouseLock() { + mouse_lock_state_ = MOUSELOCK_NOT_REQUESTED; + SetTabWithExclusiveAccess(nullptr); + NotifyMouseLockChange(); + exclusive_access_manager()->UpdateExclusiveAccessExitBubbleContent(); +} + +bool MouseLockController::IsMouseLockRequested() const { + return mouse_lock_state_ == MOUSELOCK_REQUESTED; +} + +void MouseLockController::NotifyMouseLockChange() { + content::NotificationService::current()->Notify( + chrome::NOTIFICATION_MOUSE_LOCK_CHANGED, + content::Source<MouseLockController>(this), + content::NotificationService::NoDetails()); +} + +void MouseLockController::UnlockMouse() { + WebContents* tab = exclusive_access_tab(); + + if (!tab) + return; + + content::RenderWidgetHostView* mouse_lock_view = nullptr; + FullscreenController* fullscreen_controller = + exclusive_access_manager()->fullscreen_controller(); + if ((fullscreen_controller->exclusive_access_tab() == tab) && + fullscreen_controller->IsPrivilegedFullscreenForTab()) { + mouse_lock_view = + exclusive_access_tab()->GetFullscreenRenderWidgetHostView(); + } + + if (!mouse_lock_view) { + RenderViewHost* const rvh = exclusive_access_tab()->GetRenderViewHost(); + if (rvh) + mouse_lock_view = rvh->GetView(); + } + + if (mouse_lock_view) + mouse_lock_view->UnlockMouse(); +} + +ContentSetting MouseLockController::GetMouseLockSetting(const GURL& url) const { + if (exclusive_access_manager() + ->fullscreen_controller() + ->IsPrivilegedFullscreenForTab() || + url.SchemeIsFile()) + return CONTENT_SETTING_ALLOW; + + HostContentSettingsMap* settings_map = profile()->GetHostContentSettingsMap(); + return settings_map->GetContentSetting( + url, url, CONTENT_SETTINGS_TYPE_MOUSELOCK, std::string()); +}
diff --git a/chrome/browser/ui/exclusive_access/mouse_lock_controller.h b/chrome/browser/ui/exclusive_access/mouse_lock_controller.h new file mode 100644 index 0000000..27cede2 --- /dev/null +++ b/chrome/browser/ui/exclusive_access/mouse_lock_controller.h
@@ -0,0 +1,61 @@ +// Copyright (c) 2015 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_EXCLUSIVE_ACCESS_MOUSE_LOCK_CONTROLLER_H_ +#define CHROME_BROWSER_UI_EXCLUSIVE_ACCESS_MOUSE_LOCK_CONTROLLER_H_ + +#include "chrome/browser/ui/exclusive_access/exclusive_access_controller_base.h" +#include "components/content_settings/core/common/content_settings.h" + +// This class implements mouselock behavior. +class MouseLockController : public ExclusiveAccessControllerBase { + public: + MouseLockController(ExclusiveAccessManager* manager, Browser* browser); + ~MouseLockController() override; + + bool IsMouseLocked() const; + bool IsMouseLockSilentlyAccepted() const; + bool IsMouseLockRequested() const; + + void RequestToLockMouse(content::WebContents* web_contents, + bool user_gesture, + bool last_unlocked_by_target); + + // Override from ExclusiveAccessControllerBase + bool HandleUserPressedEscape() override; + + void ExitExclusiveAccessToPreviousState() override; + bool OnAcceptExclusiveAccessPermission() override; + bool OnDenyExclusiveAccessPermission() override; + + // Called by Browser::LostMouseLock. + void LostMouseLock(); + + void UnlockMouse(); + + private: + enum MouseLockState { + MOUSELOCK_NOT_REQUESTED, + // The page requests to lock the mouse and the user hasn't responded to the + // request. + MOUSELOCK_REQUESTED, + // Mouse lock has been allowed by the user. + MOUSELOCK_ACCEPTED, + // Mouse lock has been silently accepted, no notification to user. + MOUSELOCK_ACCEPTED_SILENTLY + }; + + void NotifyMouseLockChange(); + + void ExitExclusiveAccessIfNecessary() override; + void NotifyTabExclusiveAccessLost() override; + + ContentSetting GetMouseLockSetting(const GURL& url) const; + + MouseLockState mouse_lock_state_; + + DISALLOW_COPY_AND_ASSIGN(MouseLockController); +}; + +#endif // CHROME_BROWSER_UI_EXCLUSIVE_ACCESS_MOUSE_LOCK_CONTROLLER_H_
diff --git a/chrome/browser/ui/omnibox/omnibox_edit_model.cc b/chrome/browser/ui/omnibox/omnibox_edit_model.cc index b2f07fb..a1a9d53 100644 --- a/chrome/browser/ui/omnibox/omnibox_edit_model.cc +++ b/chrome/browser/ui/omnibox/omnibox_edit_model.cc
@@ -743,8 +743,7 @@ input_.type(), popup_model()->IsOpen(), (!popup_model()->IsOpen() || !pasted_text.empty()) ? 0 : index, - !pasted_text.empty(), // is_paste_and_go - paste_state_ != NONE, // last_action_was_paste + !pasted_text.empty(), -1, // don't yet know tab ID; set later if appropriate ClassifyPage(), elapsed_time_since_user_first_modified_omnibox,
diff --git a/chrome/browser/ui/omnibox/omnibox_navigation_observer.cc b/chrome/browser/ui/omnibox/omnibox_navigation_observer.cc index 040dbdef..5002940 100644 --- a/chrome/browser/ui/omnibox/omnibox_navigation_observer.cc +++ b/chrome/browser/ui/omnibox/omnibox_navigation_observer.cc
@@ -15,6 +15,7 @@ #include "content/public/browser/navigation_entry.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/notification_types.h" +#include "content/public/browser/render_frame_host.h" #include "content/public/browser/web_contents.h" #include "net/base/load_flags.h" #include "net/base/registry_controlled_domains/registry_controlled_domain.h" @@ -86,32 +87,40 @@ const content::NotificationSource& source, const content::NotificationDetails& details) { DCHECK_EQ(content::NOTIFICATION_NAV_ENTRY_PENDING, type); - registrar_.Remove(this, content::NOTIFICATION_NAV_ENTRY_PENDING, - content::NotificationService::AllSources()); + + // It's possible for an attempted omnibox navigation to cause the extensions + // system to synchronously navigate an extension background page. Not only is + // this navigation not the one we want to observe, the associated WebContents + // is invisible and has no InfoBarService, so trying to show an infobar in it + // later will crash. Just ignore this navigation and keep listening. content::NavigationController* controller = content::Source<content::NavigationController>(source).ptr(); + content::WebContents* web_contents = controller->GetWebContents(); + if (!InfoBarService::FromWebContents(web_contents)) + return; + + // Ignore navgiations to the wrong URL. + // This shouldn't actually happen, but right now it's possible because the + // prerenderer doesn't properly notify us when it swaps in a prerendered page. + // Plus, the swap-in can trigger instant to kick off a new background + // prerender, which we _do_ get notified about. Once crbug.com/247848 is + // fixed, this conditional should be able to be replaced with a [D]CHECK; + // until then we ignore the incorrect navigation (and will be torn down + // without having received the correct notification). + if (match_.destination_url != + content::Details<content::NavigationEntry>(details)->GetVirtualURL()) + return; + + registrar_.Remove(this, content::NOTIFICATION_NAV_ENTRY_PENDING, + content::NotificationService::AllSources()); if (fetcher_) { fetcher_->SetRequestContext( controller->GetBrowserContext()->GetRequestContext()); } - WebContentsObserver::Observe(controller->GetWebContents()); + WebContentsObserver::Observe(web_contents); // DidStartNavigationToPendingEntry() will be called for this load as well. } -void OmniboxNavigationObserver::NavigationEntryCommitted( - const content::LoadCommittedDetails& load_details) { - load_state_ = LOAD_COMMITTED; - if (ResponseCodeIndicatesSuccess(load_details.http_status_code) && - IsValidNavigation(match_.destination_url, load_details.entry->GetURL())) - OnSuccessfulNavigation(); - if (!fetcher_ || (fetch_state_ != FETCH_NOT_COMPLETE)) - OnAllLoadingFinished(); // deletes |this|! -} - -void OmniboxNavigationObserver::WebContentsDestroyed() { - delete this; -} - void OmniboxNavigationObserver::DidStartNavigationToPendingEntry( const GURL& url, content::NavigationController::ReloadType reload_type) { @@ -124,6 +133,30 @@ } } +void OmniboxNavigationObserver::DidFailProvisionalLoad( + content::RenderFrameHost* render_frame_host, + const GURL& validated_url, + int error_code, + const base::string16& error_description) { + if ((load_state_ != LOAD_COMMITTED) && !render_frame_host->GetParent()) + delete this; +} + +void OmniboxNavigationObserver::NavigationEntryCommitted( + const content::LoadCommittedDetails& load_details) { + load_state_ = LOAD_COMMITTED; + if (ResponseCodeIndicatesSuccess(load_details.http_status_code) && + IsValidNavigation(match_.destination_url, + load_details.entry->GetVirtualURL())) + OnSuccessfulNavigation(); + if (!fetcher_ || (fetch_state_ != FETCH_NOT_COMPLETE)) + OnAllLoadingFinished(); // deletes |this|! +} + +void OmniboxNavigationObserver::WebContentsDestroyed() { + delete this; +} + void OmniboxNavigationObserver::OnURLFetchComplete( const net::URLFetcher* source) { DCHECK_EQ(fetcher_.get(), source);
diff --git a/chrome/browser/ui/omnibox/omnibox_navigation_observer.h b/chrome/browser/ui/omnibox/omnibox_navigation_observer.h index 82c9fd2..e7f8717 100644 --- a/chrome/browser/ui/omnibox/omnibox_navigation_observer.h +++ b/chrome/browser/ui/omnibox/omnibox_navigation_observer.h
@@ -81,6 +81,10 @@ void DidStartNavigationToPendingEntry( const GURL& url, content::NavigationController::ReloadType reload_type) override; + void DidFailProvisionalLoad(content::RenderFrameHost* render_frame_host, + const GURL& validated_url, + int error_code, + const base::string16& error_description) override; void NavigationEntryCommitted( const content::LoadCommittedDetails& load_details) override; void WebContentsDestroyed() override;
diff --git a/chrome/browser/ui/passwords/manage_passwords_bubble_model.cc b/chrome/browser/ui/passwords/manage_passwords_bubble_model.cc index f83dbb4..83cea52 100644 --- a/chrome/browser/ui/passwords/manage_passwords_bubble_model.cc +++ b/chrome/browser/ui/passwords/manage_passwords_bubble_model.cc
@@ -13,6 +13,7 @@ #include "chrome/grit/generated_resources.h" #include "components/feedback/feedback_data.h" #include "components/feedback/feedback_util.h" +#include "components/password_manager/content/common/credential_manager_types.h" #include "components/password_manager/core/browser/password_manager_url_collection_experiment.h" #include "components/password_manager/core/browser/password_store.h" #include "components/password_manager/core/common/password_manager_ui.h" @@ -121,10 +122,13 @@ state_ = controller->state(); if (password_manager::ui::IsPendingState(state_)) pending_password_ = controller->PendingPassword(); - if (password_manager::ui::IsCredentialsState(state_)) - pending_credentials_.swap(controller->new_password_forms()); - else + if (password_manager::ui::IsCredentialsState(state_)) { + local_pending_credentials_.swap(controller->local_credentials_forms()); + federated_pending_credentials_.swap( + controller->federated_credentials_forms()); + } else { best_matches_ = controller->best_matches(); + } if (password_manager::ui::IsPendingState(state_)) { title_ = PendingStateTitleBasedOnSavePasswordPref(never_save_passwords_); @@ -197,8 +201,9 @@ // OnChooseCredentials(). ManagePasswordsUIController* manage_passwords_ui_controller = ManagePasswordsUIController::FromWebContents(web_contents()); - manage_passwords_ui_controller->ChooseCredential(false, - autofill::PasswordForm()); + manage_passwords_ui_controller->ChooseCredential( + autofill::PasswordForm(), + password_manager::CredentialType::CREDENTIAL_TYPE_EMPTY); state_ = password_manager::ui::INACTIVE_STATE; } if (dismissal_reason_ == metrics_util::NOT_DISPLAYED) @@ -317,12 +322,14 @@ } void ManagePasswordsBubbleModel::OnChooseCredentials( - const autofill::PasswordForm& password_form) { + const autofill::PasswordForm& password_form, + password_manager::CredentialType credential_type) { dismissal_reason_ = metrics_util::CLICKED_CREDENTIAL; RecordExperimentStatistics(web_contents(), dismissal_reason_); ManagePasswordsUIController* manage_passwords_ui_controller = ManagePasswordsUIController::FromWebContents(web_contents()); - manage_passwords_ui_controller->ChooseCredential(true, password_form); + manage_passwords_ui_controller->ChooseCredential(password_form, + credential_type); state_ = password_manager::ui::INACTIVE_STATE; }
diff --git a/chrome/browser/ui/passwords/manage_passwords_bubble_model.h b/chrome/browser/ui/passwords/manage_passwords_bubble_model.h index eae9867..1c3693e 100644 --- a/chrome/browser/ui/passwords/manage_passwords_bubble_model.h +++ b/chrome/browser/ui/passwords/manage_passwords_bubble_model.h
@@ -21,6 +21,10 @@ class WebContents; } +namespace password_manager { +enum class CredentialType : unsigned int; +} + // This model provides data for the ManagePasswordsBubble and controls the // password management actions. class ManagePasswordsBubbleModel : public content::WebContentsObserver { @@ -82,7 +86,8 @@ PasswordAction action); // Called by the view code to notify about chosen credential. - void OnChooseCredentials(const autofill::PasswordForm& password_form); + void OnChooseCredentials(const autofill::PasswordForm& password_form, + password_manager::CredentialType credential_type_); GURL origin() const { return origin_; } @@ -95,8 +100,13 @@ const autofill::ConstPasswordFormMap& best_matches() const { return best_matches_; } - const ScopedVector<autofill::PasswordForm>& pending_credentials() const { - return pending_credentials_; + const ScopedVector<autofill::PasswordForm>& local_pending_credentials() + const { + return local_pending_credentials_; + } + const ScopedVector<autofill::PasswordForm>& federated_pending_credentials() + const { + return federated_pending_credentials_; } const base::string16& manage_link() const { return manage_link_; } bool never_save_passwords() const { return never_save_passwords_; } @@ -136,7 +146,8 @@ base::string16 title_; autofill::PasswordForm pending_password_; autofill::ConstPasswordFormMap best_matches_; - ScopedVector<autofill::PasswordForm> pending_credentials_; + ScopedVector<autofill::PasswordForm> local_pending_credentials_; + ScopedVector<autofill::PasswordForm> federated_pending_credentials_; base::string16 manage_link_; base::string16 save_confirmation_text_; gfx::Range save_confirmation_link_range_;
diff --git a/chrome/browser/ui/passwords/manage_passwords_bubble_model_unittest.cc b/chrome/browser/ui/passwords/manage_passwords_bubble_model_unittest.cc index debc516..ce77b7ff 100644 --- a/chrome/browser/ui/passwords/manage_passwords_bubble_model_unittest.cc +++ b/chrome/browser/ui/passwords/manage_passwords_bubble_model_unittest.cc
@@ -10,6 +10,7 @@ #include "chrome/browser/ui/passwords/manage_passwords_bubble_model.h" #include "chrome/browser/ui/passwords/manage_passwords_ui_controller_mock.h" #include "chrome/test/base/testing_profile.h" +#include "components/password_manager/content/common/credential_manager_types.h" #include "components/password_manager/core/browser/password_manager_metrics_util.h" #include "components/password_manager/core/browser/password_manager_url_collection_experiment.h" #include "components/password_manager/core/common/password_manager_pref_names.h" @@ -257,7 +258,8 @@ PretendCredentialsWaiting(); EXPECT_FALSE(controller()->choose_credential()); autofill::PasswordForm form; - model_->OnChooseCredentials(form); + model_->OnChooseCredentials( + form, password_manager::CredentialType::CREDENTIAL_TYPE_LOCAL); model_->OnBubbleHidden(); EXPECT_EQ(model_->dismissal_reason(), password_manager::metrics_util::CLICKED_CREDENTIAL);
diff --git a/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc b/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc index 67787ba8..7f44b42 100644 --- a/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc +++ b/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc
@@ -119,11 +119,16 @@ ScopedVector<autofill::PasswordForm> local_credentials, ScopedVector<autofill::PasswordForm> federated_credentials, base::Callback<void(const password_manager::CredentialInfo&)> callback){ - // TODO(vasilii): Do something clever with |federated_credentials|. DCHECK(!local_credentials.empty() || !federated_credentials.empty()); form_manager_.reset(); - origin_ = local_credentials[0]->origin; - new_password_forms_.swap(local_credentials); + // TODO(melandory): fix the crash when |local_credentials| is empty. + // By providing origin explicitly. + if (!local_credentials.empty()) + origin_ = local_credentials[0]->origin; + else + origin_ = GURL(); + local_credentials_forms_.swap(local_credentials); + federated_credentials_forms_.swap(federated_credentials); // The map is useless because usernames may overlap. password_form_map_.clear(); SetState(password_manager::ui::CREDENTIAL_REQUEST_AND_BUBBLE_STATE); @@ -211,13 +216,12 @@ } void ManagePasswordsUIController::ChooseCredential( - bool was_chosen, - const autofill::PasswordForm& form) { + const autofill::PasswordForm& form, + password_manager::CredentialType credential_type) { DCHECK(password_manager::ui::IsCredentialsState(state_)); DCHECK(!credentials_callback_.is_null()); - password_manager::CredentialInfo info = was_chosen ? - password_manager::CredentialInfo(form) : - password_manager::CredentialInfo(); + password_manager::CredentialInfo info = + password_manager::CredentialInfo(form, credential_type); credentials_callback_.Run(info); SetState(password_manager::ui::INACTIVE_STATE); UpdateBubbleAndIconVisibility();
diff --git a/chrome/browser/ui/passwords/manage_passwords_ui_controller.h b/chrome/browser/ui/passwords/manage_passwords_ui_controller.h index 5a1838e..8397b80 100644 --- a/chrome/browser/ui/passwords/manage_passwords_ui_controller.h +++ b/chrome/browser/ui/passwords/manage_passwords_ui_controller.h
@@ -18,6 +18,7 @@ } namespace password_manager { +enum class CredentialType : unsigned int; struct CredentialInfo; class PasswordFormManager; } @@ -80,8 +81,9 @@ // Called from the model when the user chooses a credential. // The controller MUST be in a pending credentials state. - virtual void ChooseCredential(bool was_chosen, - const autofill::PasswordForm& form); + virtual void ChooseCredential( + const autofill::PasswordForm& form, + password_manager::CredentialType credential_type); // Called from the model when the user chooses to never save passwords; passes // the action off to the FormManager. The controller MUST be in a pending @@ -107,8 +109,12 @@ password_manager::ui::State state() const { return state_; } - ScopedVector<autofill::PasswordForm>& new_password_forms() { - return new_password_forms_; + ScopedVector<autofill::PasswordForm>& federated_credentials_forms() { + return federated_credentials_forms_; + } + + ScopedVector<autofill::PasswordForm>& local_credentials_forms() { + return local_credentials_forms_; } // True if a password is sitting around, waiting for a user to decide whether @@ -154,6 +160,14 @@ // |password_form_map_| is to be cleared too. ScopedVector<autofill::PasswordForm> new_password_forms_; + // Federated credentials. Stores federated credentials which will be shown + // when Credential Management API was used. + ScopedVector<autofill::PasswordForm> federated_credentials_forms_; + + // Local credentials. Stores local credentials which will be shown + // when Credential Management API was used. + ScopedVector<autofill::PasswordForm> local_credentials_forms_; + // All previously stored credentials for a specific site. // Protected, not private, so we can mess with the value in // ManagePasswordsUIControllerMock.
diff --git a/chrome/browser/ui/passwords/manage_passwords_ui_controller_mock.cc b/chrome/browser/ui/passwords/manage_passwords_ui_controller_mock.cc index 3d1b7de..5c62a52 100644 --- a/chrome/browser/ui/passwords/manage_passwords_ui_controller_mock.cc +++ b/chrome/browser/ui/passwords/manage_passwords_ui_controller_mock.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/ui/passwords/manage_passwords_ui_controller_mock.h" +#include "components/password_manager/content/common/credential_manager_types.h" #include "content/public/browser/web_contents.h" #include "testing/gtest/include/gtest/gtest.h" @@ -60,8 +61,8 @@ } void ManagePasswordsUIControllerMock::ChooseCredential( - bool was_chosen, - const autofill::PasswordForm& form) { + const autofill::PasswordForm& form, + password_manager::CredentialType form_type) { EXPECT_FALSE(choose_credential_); choose_credential_ = true; }
diff --git a/chrome/browser/ui/passwords/manage_passwords_ui_controller_mock.h b/chrome/browser/ui/passwords/manage_passwords_ui_controller_mock.h index d704f39..8f741f3f 100644 --- a/chrome/browser/ui/passwords/manage_passwords_ui_controller_mock.h +++ b/chrome/browser/ui/passwords/manage_passwords_ui_controller_mock.h
@@ -14,6 +14,10 @@ class WebContents; } // namespace content +namespace password_manager { +enum class CredentialType : unsigned int; +} + // This mock is used in tests to ensure that we're just testing the controller // behavior, and not the behavior of the bits and pieces it relies upon (like // FormManager). @@ -40,8 +44,8 @@ void NeverSavePasswordInternal() override; bool never_saved_password() const { return never_saved_password_; } - void ChooseCredential(bool was_chosen, - const autofill::PasswordForm& form) override; + void ChooseCredential(const autofill::PasswordForm& form, + password_manager::CredentialType form_type) override; bool choose_credential() const { return choose_credential_; } const autofill::PasswordForm& PendingPassword() const override;
diff --git a/chrome/browser/ui/passwords/manage_passwords_ui_controller_unittest.cc b/chrome/browser/ui/passwords/manage_passwords_ui_controller_unittest.cc index c12acc68..b91b74b5 100644 --- a/chrome/browser/ui/passwords/manage_passwords_ui_controller_unittest.cc +++ b/chrome/browser/ui/passwords/manage_passwords_ui_controller_unittest.cc
@@ -322,7 +322,7 @@ EXPECT_EQ(password_manager::ui::MANAGE_STATE, mock.state()); } -TEST_F(ManagePasswordsUIControllerTest, ChooseCredential) { +TEST_F(ManagePasswordsUIControllerTest, ChooseCredentialLocal) { ScopedVector<autofill::PasswordForm> local_credentials; local_credentials.push_back(new autofill::PasswordForm(test_form())); ScopedVector<autofill::PasswordForm> federated_credentials; @@ -341,16 +341,44 @@ controller()->UpdateIconAndBubbleState(&mock); EXPECT_EQ(password_manager::ui::CREDENTIAL_REQUEST_STATE, mock.state()); - controller()->ManagePasswordsUIController::ChooseCredential(true, - test_form()); + controller()->ManagePasswordsUIController::ChooseCredential( + test_form(), password_manager::CredentialType::CREDENTIAL_TYPE_LOCAL); EXPECT_EQ(password_manager::ui::INACTIVE_STATE, controller()->state()); ASSERT_TRUE(credential_info()); EXPECT_EQ(test_form().username_value, credential_info()->id); EXPECT_EQ(test_form().password_value, credential_info()->password); + EXPECT_TRUE(credential_info()->federation.is_empty()); EXPECT_EQ(password_manager::CredentialType::CREDENTIAL_TYPE_LOCAL, credential_info()->type); } +TEST_F(ManagePasswordsUIControllerTest, ChooseCredentialFederated) { + ScopedVector<autofill::PasswordForm> local_credentials; + ScopedVector<autofill::PasswordForm> federated_credentials; + federated_credentials.push_back(new autofill::PasswordForm(test_form())); + EXPECT_TRUE(controller()->OnChooseCredentials( + local_credentials.Pass(), federated_credentials.Pass(), + base::Bind(&ManagePasswordsUIControllerTest::CredentialCallback, + base::Unretained(this)))); + EXPECT_EQ(password_manager::ui::CREDENTIAL_REQUEST_AND_BUBBLE_STATE, + controller()->state()); + EXPECT_FALSE(controller()->PasswordPendingUserDecision()); + EXPECT_EQ(autofill::ConstPasswordFormMap(), controller()->best_matches()); + + ManagePasswordsIconMock mock; + controller()->UpdateIconAndBubbleState(&mock); + EXPECT_EQ(password_manager::ui::CREDENTIAL_REQUEST_STATE, mock.state()); + + controller()->ManagePasswordsUIController::ChooseCredential( + test_form(), password_manager::CredentialType::CREDENTIAL_TYPE_FEDERATED); + EXPECT_EQ(password_manager::ui::INACTIVE_STATE, controller()->state()); + ASSERT_TRUE(credential_info()); + EXPECT_EQ(test_form().username_value, credential_info()->id); + EXPECT_TRUE(credential_info()->password.empty()); + EXPECT_EQ(password_manager::CredentialType::CREDENTIAL_TYPE_FEDERATED, + credential_info()->type); +} + TEST_F(ManagePasswordsUIControllerTest, ChooseCredentialCancel) { ScopedVector<autofill::PasswordForm> local_credentials; local_credentials.push_back(new autofill::PasswordForm(test_form())); @@ -363,10 +391,12 @@ EXPECT_EQ(password_manager::ui::CREDENTIAL_REQUEST_AND_BUBBLE_STATE, controller()->state()); - controller()->ManagePasswordsUIController::ChooseCredential(false, - test_form()); + controller()->ManagePasswordsUIController::ChooseCredential( + test_form(), password_manager::CredentialType::CREDENTIAL_TYPE_EMPTY); EXPECT_EQ(password_manager::ui::INACTIVE_STATE, controller()->state()); ASSERT_TRUE(credential_info()); + EXPECT_TRUE(credential_info()->federation.is_empty()); + EXPECT_TRUE(credential_info()->password.empty()); EXPECT_EQ(password_manager::CredentialType::CREDENTIAL_TYPE_EMPTY, credential_info()->type); }
diff --git a/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc b/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc index 2aea5d5..ea89f45 100644 --- a/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc +++ b/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
@@ -127,9 +127,7 @@ void SetAppLaunchPref(const std::string& app_id, extensions::LaunchType launch_type) { - ExtensionService* service = extensions::ExtensionSystem::Get( - browser()->profile())->extension_service(); - extensions::SetLaunchType(service, app_id, launch_type); + extensions::SetLaunchType(browser()->profile(), app_id, launch_type); } Browser* FindOneOtherBrowserForProfile(Profile* profile,
diff --git a/chrome/browser/ui/sync/one_click_signin_sync_observer_unittest.cc b/chrome/browser/ui/sync/one_click_signin_sync_observer_unittest.cc index 69e94a3..3c5e051 100644 --- a/chrome/browser/ui/sync/one_click_signin_sync_observer_unittest.cc +++ b/chrome/browser/ui/sync/one_click_signin_sync_observer_unittest.cc
@@ -38,7 +38,8 @@ // to the continue URL. Navigations in unit_tests never complete, but a // navigation start is a sufficient signal for the purposes of this test. // Listening for this call also has the advantage of being synchronous. - MOCK_METHOD1(AboutToNavigateRenderFrame, void(content::RenderFrameHost*)); + MOCK_METHOD2(AboutToNavigateRenderFrame, void(content::RenderFrameHost*, + content::RenderFrameHost*)); }; class OneClickTestProfileSyncService : public TestProfileSyncService { @@ -169,7 +170,7 @@ profile(), BuildNullService)); // The observer should immediately redirect to the continue URL. - EXPECT_CALL(*web_contents_observer_, AboutToNavigateRenderFrame(_)); + EXPECT_CALL(*web_contents_observer_, AboutToNavigateRenderFrame(_, _)); CreateSyncObserver(kContinueUrl); EXPECT_EQ(GURL(kContinueUrl), web_contents()->GetVisibleURL()); @@ -181,7 +182,8 @@ // Verify that when the WebContents is destroyed without any Sync notifications // firing, the observer cleans up its memory without loading the continue URL. TEST_F(OneClickSigninSyncObserverTest, WebContentsDestroyed) { - EXPECT_CALL(*web_contents_observer_, AboutToNavigateRenderFrame(_)).Times(0); + EXPECT_CALL(*web_contents_observer_, + AboutToNavigateRenderFrame(_, _)).Times(0); CreateSyncObserver(kContinueUrl); SetContents(NULL); } @@ -194,7 +196,7 @@ sync_service_->set_first_setup_in_progress(false); sync_service_->set_sync_active(true); - EXPECT_CALL(*web_contents_observer_, AboutToNavigateRenderFrame(_)); + EXPECT_CALL(*web_contents_observer_, AboutToNavigateRenderFrame(_, _)); sync_service_->NotifyObservers(); EXPECT_EQ(GURL(kContinueUrl), web_contents()->GetVisibleURL()); } @@ -207,7 +209,8 @@ sync_service_->set_first_setup_in_progress(false); sync_service_->set_sync_active(false); - EXPECT_CALL(*web_contents_observer_, AboutToNavigateRenderFrame(_)).Times(0); + EXPECT_CALL(*web_contents_observer_, + AboutToNavigateRenderFrame(_, _)).Times(0); sync_service_->NotifyObservers(); EXPECT_NE(GURL(kContinueUrl), web_contents()->GetVisibleURL()); } @@ -220,7 +223,8 @@ sync_service_->set_first_setup_in_progress(true); sync_service_->set_sync_active(false); - EXPECT_CALL(*web_contents_observer_, AboutToNavigateRenderFrame(_)).Times(0); + EXPECT_CALL(*web_contents_observer_, + AboutToNavigateRenderFrame(_, _)).Times(0); sync_service_->NotifyObservers(); EXPECT_NE(GURL(kContinueUrl), web_contents()->GetVisibleURL()); @@ -238,7 +242,8 @@ sync_service_->set_first_setup_in_progress(false); sync_service_->set_sync_active(true); - EXPECT_CALL(*web_contents_observer_, AboutToNavigateRenderFrame(_)).Times(0); + EXPECT_CALL(*web_contents_observer_, + AboutToNavigateRenderFrame(_, _)).Times(0); sync_service_->NotifyObservers(); EXPECT_NE(GURL(kContinueUrl), web_contents()->GetVisibleURL()); }
diff --git a/chrome/browser/ui/toolbar/toolbar_model_impl.cc b/chrome/browser/ui/toolbar/toolbar_model_impl.cc index 8f2edcd0..bff5959d 100644 --- a/chrome/browser/ui/toolbar/toolbar_model_impl.cc +++ b/chrome/browser/ui/toolbar/toolbar_model_impl.cc
@@ -65,6 +65,27 @@ return true; } +ToolbarModel::SecurityLevel GetSecurityLevelForNonSecureFieldTrial() { + std::string choice = base::CommandLine::ForCurrentProcess()-> + GetSwitchValueASCII(switches::kMarkNonSecureAs); + if (choice == switches::kMarkNonSecureAsNeutral) + return ToolbarModel::NONE; + if (choice == switches::kMarkNonSecureAsDubious) + return ToolbarModel::SECURITY_WARNING; + if (choice == switches::kMarkNonSecureAsNonSecure) + return ToolbarModel::SECURITY_ERROR; + + std::string group = base::FieldTrialList::FindFullName("MarkNonSecureAs"); + if (group == switches::kMarkNonSecureAsNeutral) + return ToolbarModel::NONE; + if (group == switches::kMarkNonSecureAsDubious) + return ToolbarModel::SECURITY_WARNING; + if (group == switches::kMarkNonSecureAsNonSecure) + return ToolbarModel::SECURITY_ERROR; + + return ToolbarModel::NONE; +} + } // namespace ToolbarModelImpl::ToolbarModelImpl(ToolbarModelDelegate* delegate) @@ -87,9 +108,15 @@ const SSLStatus& ssl = entry->GetSSL(); switch (ssl.security_style) { case content::SECURITY_STYLE_UNKNOWN: - case content::SECURITY_STYLE_UNAUTHENTICATED: return NONE; + case content::SECURITY_STYLE_UNAUTHENTICATED: { + const GURL& url = entry->GetURL(); + if (url.SchemeIs("http") || url.SchemeIs("ftp")) + return GetSecurityLevelForNonSecureFieldTrial(); + return NONE; + } + case content::SECURITY_STYLE_AUTHENTICATION_BROKEN: return SECURITY_ERROR;
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_header_panel.cc b/chrome/browser/ui/views/apps/app_info_dialog/app_info_header_panel.cc index 6e2ffa8..b54725b 100644 --- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_header_panel.cc +++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_header_panel.cc
@@ -139,5 +139,7 @@ } bool AppInfoHeaderPanel::CanShowAppInWebStore() const { - return app_->from_webstore(); + // Hide the webstore link for apps which were installed by default, + // since this could leak user counts for OEM-specific apps. + return app_->from_webstore() && !app_->was_installed_by_default(); }
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_panel.cc b/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_panel.cc index 44afa03..e88693f 100644 --- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_panel.cc +++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_panel.cc
@@ -302,9 +302,7 @@ void AppInfoSummaryPanel::SetLaunchType( extensions::LaunchType launch_type) const { DCHECK(CanSetLaunchType()); - ExtensionService* service = - extensions::ExtensionSystem::Get(profile_)->extension_service(); - extensions::SetLaunchType(service, app_->id(), launch_type); + extensions::SetLaunchType(profile_, app_->id(), launch_type); } bool AppInfoSummaryPanel::CanSetLaunchType() const {
diff --git a/chrome/browser/ui/views/autofill/card_unmask_prompt_views.cc b/chrome/browser/ui/views/autofill/card_unmask_prompt_views.cc index cf21a188..e004ae39 100644 --- a/chrome/browser/ui/views/autofill/card_unmask_prompt_views.cc +++ b/chrome/browser/ui/views/autofill/card_unmask_prompt_views.cc
@@ -4,6 +4,7 @@ #include "base/basictypes.h" #include "base/strings/utf_string_conversions.h" +#include "chrome/browser/ui/autofill/autofill_dialog_models.h" #include "chrome/browser/ui/autofill/card_unmask_prompt_controller.h" #include "chrome/browser/ui/autofill/card_unmask_prompt_view.h" #include "chrome/grit/generated_resources.h" @@ -11,6 +12,8 @@ #include "grit/theme_resources.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" +#include "ui/views/controls/combobox/combobox.h" +#include "ui/views/controls/combobox/combobox_listener.h" #include "ui/views/controls/image_view.h" #include "ui/views/controls/label.h" #include "ui/views/controls/textfield/textfield.h" @@ -25,11 +28,16 @@ namespace { class CardUnmaskPromptViews : public CardUnmaskPromptView, + views::ComboboxListener, views::DialogDelegateView, views::TextfieldController { public: explicit CardUnmaskPromptViews(CardUnmaskPromptController* controller) - : controller_(controller), cvc_input_(nullptr), message_label_(nullptr) {} + : controller_(controller), + cvc_input_(nullptr), + month_input_(nullptr), + year_input_(nullptr), + message_label_(nullptr) {} ~CardUnmaskPromptViews() override { if (controller_) @@ -48,7 +56,7 @@ } void DisableAndWaitForVerification() override { - cvc_input_->SetEnabled(false); + SetInputsEnabled(false); message_label_->SetText(base::ASCIIToUTF16("Verifying...")); message_label_->SetVisible(true); GetDialogClientView()->UpdateDialogButtons(); @@ -63,13 +71,22 @@ base::Unretained(this)), base::TimeDelta::FromSeconds(1)); } else { - cvc_input_->SetEnabled(true); + SetInputsEnabled(true); message_label_->SetText(base::ASCIIToUTF16("Verification error.")); GetDialogClientView()->UpdateDialogButtons(); } Layout(); } + void SetInputsEnabled(bool enabled) { + cvc_input_->SetEnabled(enabled); + + if (month_input_) + month_input_->SetEnabled(enabled); + if (year_input_) + year_input_->SetEnabled(enabled); + } + // views::DialogDelegateView View* GetContentsView() override { InitIfNecessary(); @@ -114,7 +131,13 @@ DCHECK_EQ(ui::DIALOG_BUTTON_OK, button); return cvc_input_->enabled() && - controller_->InputTextIsValid(cvc_input_->text()); + controller_->InputTextIsValid(cvc_input_->text()) && + (!month_input_ || + month_input_->selected_index() != + month_combobox_model_.GetDefaultIndex()) && + (!year_input_ || + year_input_->selected_index() != + year_combobox_model_.GetDefaultIndex()); } views::View* GetInitiallyFocusedView() override { return cvc_input_; } @@ -127,7 +150,14 @@ if (!controller_) return true; - controller_->OnUnmaskResponse(cvc_input_->text()); + controller_->OnUnmaskResponse( + cvc_input_->text(), + month_input_ + ? month_combobox_model_.GetItemAt(month_input_->selected_index()) + : base::string16(), + year_input_ + ? year_combobox_model_.GetItemAt(year_input_->selected_index()) + : base::string16()); return false; } @@ -137,6 +167,11 @@ GetDialogClientView()->UpdateDialogButtons(); } + // views::ComboboxListener + void OnPerformAction(views::Combobox* combobox) override { + GetDialogClientView()->UpdateDialogButtons(); + } + private: void InitIfNecessary() { if (has_children()) @@ -151,27 +186,36 @@ instructions->SetHorizontalAlignment(gfx::ALIGN_LEFT); AddChildView(instructions); - views::View* cvc_container = new views::View(); - cvc_container->SetLayoutManager( + views::View* input_row = new views::View(); + input_row->SetLayoutManager( new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 5)); - AddChildView(cvc_container); + AddChildView(input_row); + + if (controller_->ShouldRequestExpirationDate()) { + month_input_ = new views::Combobox(&month_combobox_model_); + month_input_->set_listener(this); + input_row->AddChildView(month_input_); + year_input_ = new views::Combobox(&year_combobox_model_); + year_input_->set_listener(this); + input_row->AddChildView(year_input_); + } cvc_input_ = new views::Textfield(); cvc_input_->set_controller(this); cvc_input_->set_placeholder_text( l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_PLACEHOLDER_CVC)); cvc_input_->set_default_width_in_chars(10); - cvc_container->AddChildView(cvc_input_); + input_row->AddChildView(cvc_input_); views::ImageView* cvc_image = new views::ImageView(); ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); cvc_image->SetImage(rb.GetImageSkiaNamed(controller_->GetCvcImageRid())); - cvc_container->AddChildView(cvc_image); + input_row->AddChildView(cvc_image); message_label_ = new views::Label(); - cvc_container->AddChildView(message_label_); + input_row->AddChildView(message_label_); message_label_->SetVisible(false); } @@ -181,6 +225,13 @@ views::Textfield* cvc_input_; + // These will be null when expiration date is not required. + views::Combobox* month_input_; + views::Combobox* year_input_; + + MonthComboboxModel month_combobox_model_; + YearComboboxModel year_combobox_model_; + // TODO(estade): this is a temporary standin in place of some spinner UI // as well as a better error message. views::Label* message_label_;
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_instructions_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_bar_instructions_view.cc index 1990e99..7c5787ba 100644 --- a/chrome/browser/ui/views/bookmarks/bookmark_bar_instructions_view.cc +++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_instructions_view.cc
@@ -87,6 +87,10 @@ } } +const char* BookmarkBarInstructionsView::GetClassName() const { + return "BookmarkBarInstructionsView"; +} + void BookmarkBarInstructionsView::OnThemeChanged() { UpdateColors(); }
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_instructions_view.h b/chrome/browser/ui/views/bookmarks/bookmark_bar_instructions_view.h index 0ac06c0..2fd2c41 100644 --- a/chrome/browser/ui/views/bookmarks/bookmark_bar_instructions_view.h +++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_instructions_view.h
@@ -30,18 +30,20 @@ explicit BookmarkBarInstructionsView( BookmarkBarInstructionsDelegate* delegate); - // views::View overrides. + private: + // views::View: gfx::Size GetPreferredSize() const override; void Layout() override; + const char* GetClassName() const override; void OnThemeChanged() override; void ViewHierarchyChanged( const ViewHierarchyChangedDetails& details) override; void GetAccessibleState(ui::AXViewState* state) override; - // views::LinkListener overrides. + // views::LinkListener: void LinkClicked(views::Link* source, int event_flags) override; - private: + // views::ContextMenuController: void ShowContextMenuForView(views::View* source, const gfx::Point& point, ui::MenuSourceType source_type) override;
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.cc index 3f5c439..64a6e0c8 100644 --- a/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.cc +++ b/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.cc
@@ -109,10 +109,6 @@ delete parent_combobox_; } -views::View* BookmarkBubbleView::GetInitiallyFocusedView() { - return title_tf_; -} - void BookmarkBubbleView::WindowClosing() { // We have to reset |bubble_| here, not in our destructor, because we'll be // destroyed asynchronously and the shown state will be checked before then. @@ -262,6 +258,14 @@ AddAccelerator(ui::Accelerator(ui::VKEY_R, ui::EF_ALT_DOWN)); } +const char* BookmarkBubbleView::GetClassName() const { + return "BookmarkBubbleView"; +} + +views::View* BookmarkBubbleView::GetInitiallyFocusedView() { + return title_tf_; +} + BookmarkBubbleView::BookmarkBubbleView( views::View* anchor_view, BookmarkBubbleViewObserver* observer,
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.h b/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.h index 244587d..08e46d9 100644 --- a/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.h +++ b/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.h
@@ -46,13 +46,8 @@ ~BookmarkBubbleView() override; - // views::BubbleDelegateView method. - views::View* GetInitiallyFocusedView() override; - - // views::WidgetDelegate method. + // views::WidgetDelegate: void WindowClosing() override; - - // views::View method. bool AcceleratorPressed(const ui::Accelerator& accelerator) override; protected: @@ -64,6 +59,10 @@ FRIEND_TEST_ALL_PREFIXES(BookmarkBubbleViewTest, SyncPromoSignedIn); FRIEND_TEST_ALL_PREFIXES(BookmarkBubbleViewTest, SyncPromoNotSignedIn); + // views::BubbleDelegateView: + const char* GetClassName() const override; + views::View* GetInitiallyFocusedView() override; + // Creates a BookmarkBubbleView. BookmarkBubbleView(views::View* anchor_view, BookmarkBubbleViewObserver* observer,
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_editor_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_editor_view.cc index 53fbab8..484da8c6 100644 --- a/chrome/browser/ui/views/bookmarks/bookmark_editor_view.cc +++ b/chrome/browser/ui/views/bookmarks/bookmark_editor_view.cc
@@ -266,6 +266,52 @@ } } +const char* BookmarkEditorView::GetClassName() const { + return "BookmarkEditorView"; +} + +void BookmarkEditorView::BookmarkNodeMoved(BookmarkModel* model, + const BookmarkNode* old_parent, + int old_index, + const BookmarkNode* new_parent, + int new_index) { + Reset(); +} + +void BookmarkEditorView::BookmarkNodeAdded(BookmarkModel* model, + const BookmarkNode* parent, + int index) { + Reset(); +} + +void BookmarkEditorView::BookmarkNodeRemoved( + BookmarkModel* model, + const BookmarkNode* parent, + int index, + const BookmarkNode* node, + const std::set<GURL>& removed_urls) { + if ((details_.type == EditDetails::EXISTING_NODE && + details_.existing_node->HasAncestor(node)) || + (parent_ && parent_->HasAncestor(node))) { + // The node, or its parent was removed. Close the dialog. + GetWidget()->Close(); + } else { + Reset(); + } +} + +void BookmarkEditorView::BookmarkAllUserNodesRemoved( + BookmarkModel* model, + const std::set<GURL>& removed_urls) { + Reset(); +} + +void BookmarkEditorView::BookmarkNodeChildrenReordered( + BookmarkModel* model, + const BookmarkNode* node) { + Reset(); +} + void BookmarkEditorView::Init() { bb_model_->AddObserver(this); @@ -365,48 +411,6 @@ Reset(); } -void BookmarkEditorView::BookmarkNodeMoved(BookmarkModel* model, - const BookmarkNode* old_parent, - int old_index, - const BookmarkNode* new_parent, - int new_index) { - Reset(); -} - -void BookmarkEditorView::BookmarkNodeAdded(BookmarkModel* model, - const BookmarkNode* parent, - int index) { - Reset(); -} - -void BookmarkEditorView::BookmarkNodeRemoved( - BookmarkModel* model, - const BookmarkNode* parent, - int index, - const BookmarkNode* node, - const std::set<GURL>& removed_urls) { - if ((details_.type == EditDetails::EXISTING_NODE && - details_.existing_node->HasAncestor(node)) || - (parent_ && parent_->HasAncestor(node))) { - // The node, or its parent was removed. Close the dialog. - GetWidget()->Close(); - } else { - Reset(); - } -} - -void BookmarkEditorView::BookmarkAllUserNodesRemoved( - BookmarkModel* model, - const std::set<GURL>& removed_urls) { - Reset(); -} - -void BookmarkEditorView::BookmarkNodeChildrenReordered( - BookmarkModel* model, - const BookmarkNode* node) { - Reset(); -} - void BookmarkEditorView::Reset() { if (!show_tree_) { if (parent())
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_editor_view.h b/chrome/browser/ui/views/bookmarks/bookmark_editor_view.h index 8adafa7..2ff02118 100644 --- a/chrome/browser/ui/views/bookmarks/bookmark_editor_view.h +++ b/chrome/browser/ui/views/bookmarks/bookmark_editor_view.h
@@ -122,9 +122,8 @@ private: friend class BookmarkEditorViewTest; - // Creates the necessary sub-views, configures them, adds them to the layout, - // and requests the entries to display from the database. - void Init(); + // views::DialogDelegateView: + const char* GetClassName() const override; // bookmarks::BookmarkModelObserver: // Any structural change results in resetting the tree model. @@ -152,6 +151,10 @@ void BookmarkNodeFaviconChanged(bookmarks::BookmarkModel* model, const BookmarkNode* node) override {} + // Creates the necessary sub-views, configures them, adds them to the layout, + // and requests the entries to display from the database. + void Init(); + // Resets the model of the tree and updates the various buttons appropriately. void Reset();
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_sync_promo_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_sync_promo_view.cc index c5d624f..9332471 100644 --- a/chrome/browser/ui/views/bookmarks/bookmark_sync_promo_view.cc +++ b/chrome/browser/ui/views/bookmarks/bookmark_sync_promo_view.cc
@@ -74,3 +74,7 @@ int event_flags) { delegate_->OnSignInLinkClicked(); } + +const char* BookmarkSyncPromoView::GetClassName() const { + return "BookmarkSyncPromoView"; +}
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_sync_promo_view.h b/chrome/browser/ui/views/bookmarks/bookmark_sync_promo_view.h index 7d106d8f6..63efab1 100644 --- a/chrome/browser/ui/views/bookmarks/bookmark_sync_promo_view.h +++ b/chrome/browser/ui/views/bookmarks/bookmark_sync_promo_view.h
@@ -24,6 +24,9 @@ void StyledLabelLinkClicked(const gfx::Range& range, int event_flags) override; + // views::View: + const char* GetClassName() const override; + // Delegate, to handle clicks on the sign in link. BookmarkBubbleDelegate* delegate_;
diff --git a/chrome/browser/ui/views/chrome_javascript_native_dialog_factory_views.cc b/chrome/browser/ui/views/chrome_javascript_native_dialog_factory_views.cc index c7657ef..e6ebf96c 100644 --- a/chrome/browser/ui/views/chrome_javascript_native_dialog_factory_views.cc +++ b/chrome/browser/ui/views/chrome_javascript_native_dialog_factory_views.cc
@@ -7,6 +7,8 @@ #include "components/app_modal/javascript_dialog_manager.h" #include "components/app_modal/javascript_native_dialog_factory.h" #include "components/constrained_window/constrained_window_views.h" +#include "content/public/browser/web_contents.h" +#include "content/public/browser/web_contents_delegate.h" #if defined(USE_X11) && !defined(OS_CHROMEOS) #include "chrome/browser/ui/views/javascript_app_modal_dialog_views_x11.h" @@ -16,6 +18,10 @@ #include "components/app_modal/views/javascript_app_modal_dialog_views.h" #endif +#if defined(USE_AURA) +#include "ui/aura/window.h" +#endif + namespace { #if !defined(USE_X11) || defined(OS_CHROMEOS) @@ -43,14 +49,25 @@ private: app_modal::NativeAppModalDialog* CreateNativeJavaScriptDialog( - app_modal::JavaScriptAppModalDialog* dialog, - gfx::NativeWindow parent_window) override{ + app_modal::JavaScriptAppModalDialog* dialog) override { app_modal::JavaScriptAppModalDialogViews* d = nullptr; #if defined(USE_X11) && !defined(OS_CHROMEOS) d = new JavaScriptAppModalDialogViewsX11(dialog); #else d = new ChromeJavaScriptAppModalDialogViews(dialog); #endif + + dialog->web_contents()->GetDelegate()->ActivateContents( + dialog->web_contents()); + gfx::NativeWindow parent_window = + dialog->web_contents()->GetTopLevelNativeWindow(); +#if defined(USE_AURA) + if (!parent_window->GetRootWindow()) { + // When we are part of a WebContents that isn't actually being displayed + // on the screen, we can't actually attach to it. + parent_window = NULL; + } +#endif constrained_window::CreateBrowserModalDialogViews(d, parent_window); return d; }
diff --git a/chrome/browser/ui/views/exclusive_access_bubble_views.cc b/chrome/browser/ui/views/exclusive_access_bubble_views.cc index 94fa862..902bdc2 100644 --- a/chrome/browser/ui/views/exclusive_access_bubble_views.cc +++ b/chrome/browser/ui/views/exclusive_access_bubble_views.cc
@@ -8,6 +8,7 @@ #include "base/strings/utf_string_conversions.h" #include "chrome/app/chrome_command_ids.h" #include "chrome/browser/chrome_notification_types.h" +#include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/frame/immersive_mode_controller.h" @@ -295,9 +296,11 @@ popup_->AddObserver(this); - registrar_.Add(this, chrome::NOTIFICATION_FULLSCREEN_CHANGED, - content::Source<FullscreenController>( - browser_view_->browser()->fullscreen_controller())); + registrar_.Add( + this, chrome::NOTIFICATION_FULLSCREEN_CHANGED, + content::Source<FullscreenController>(browser_view_->browser() + ->exclusive_access_manager() + ->fullscreen_controller())); UpdateForImmersiveState(); }
diff --git a/chrome/browser/ui/views/extensions/bookmark_app_bubble_view.cc b/chrome/browser/ui/views/extensions/bookmark_app_bubble_view.cc index 6f570920..934e8a9 100644 --- a/chrome/browser/ui/views/extensions/bookmark_app_bubble_view.cc +++ b/chrome/browser/ui/views/extensions/bookmark_app_bubble_view.cc
@@ -89,7 +89,7 @@ extension_id_(extension_id), add_button_(NULL), cancel_button_(NULL), - open_as_tab_checkbox_(NULL), + open_as_window_checkbox_(NULL), title_tf_(NULL), remove_app_(true), app_icon_loader_(new extensions::AppIconLoaderImpl(profile, @@ -188,13 +188,13 @@ layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); layout->StartRow(0, CONTENT_COLUMN_SET_ID); - open_as_tab_checkbox_ = new views::Checkbox( - l10n_util::GetStringUTF16(IDS_BOOKMARK_APP_BUBBLE_OPEN_AS_TAB)); - open_as_tab_checkbox_->SetChecked( + open_as_window_checkbox_ = new views::Checkbox( + l10n_util::GetStringUTF16(IDS_BOOKMARK_APP_BUBBLE_OPEN_AS_WINDOW)); + open_as_window_checkbox_->SetChecked( profile_->GetPrefs()->GetInteger( extensions::pref_names::kBookmarkAppCreationLaunchType) == - extensions::LAUNCH_TYPE_REGULAR); - layout->AddView(open_as_tab_checkbox_); + extensions::LAUNCH_TYPE_WINDOW); + layout->AddView(open_as_window_checkbox_); layout->AddView(add_button_); layout->AddView(cancel_button_); layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing); @@ -261,14 +261,12 @@ void BookmarkAppBubbleView::ApplyEdits() { // Set the launch type based on the checkbox. - extensions::LaunchType launch_type = open_as_tab_checkbox_->checked() - ? extensions::LAUNCH_TYPE_REGULAR - : extensions::LAUNCH_TYPE_WINDOW; + extensions::LaunchType launch_type = open_as_window_checkbox_->checked() + ? extensions::LAUNCH_TYPE_WINDOW + : extensions::LAUNCH_TYPE_REGULAR; profile_->GetPrefs()->SetInteger( extensions::pref_names::kBookmarkAppCreationLaunchType, launch_type); - extensions::SetLaunchType(GetExtensionService(profile_), - extension_id_, - launch_type); + extensions::SetLaunchType(profile_, extension_id_, launch_type); const extensions::Extension* extension = extensions::ExtensionRegistry::Get(profile_)->GetExtensionById(
diff --git a/chrome/browser/ui/views/extensions/bookmark_app_bubble_view.h b/chrome/browser/ui/views/extensions/bookmark_app_bubble_view.h index 1b4de06..0bdb2d5a 100644 --- a/chrome/browser/ui/views/extensions/bookmark_app_bubble_view.h +++ b/chrome/browser/ui/views/extensions/bookmark_app_bubble_view.h
@@ -93,8 +93,8 @@ // Button to close the window. views::LabelButton* cancel_button_; - // Checkbox to launch as a tab. - views::Checkbox* open_as_tab_checkbox_; + // Checkbox to launch as a window. + views::Checkbox* open_as_window_checkbox_; // Textfield showing the title of the app. views::Textfield* title_tf_;
diff --git a/chrome/browser/ui/views/find_bar_view.cc b/chrome/browser/ui/views/find_bar_view.cc index d01cb9c..57373ea 100644 --- a/chrome/browser/ui/views/find_bar_view.cc +++ b/chrome/browser/ui/views/find_bar_view.cc
@@ -495,6 +495,10 @@ return static_cast<FindBarHost*>(host()); } +const char* FindBarView::GetClassName() const { + return "FindBarView"; +} + void FindBarView::OnThemeChanged() { ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); if (GetThemeProvider()) {
diff --git a/chrome/browser/ui/views/find_bar_view.h b/chrome/browser/ui/views/find_bar_view.h index 8382b02..88172d8 100644 --- a/chrome/browser/ui/views/find_bar_view.h +++ b/chrome/browser/ui/views/find_bar_view.h
@@ -67,7 +67,7 @@ // Claims focus for the text field and selects its contents. void SetFocusAndSelection(bool select_all) override; - // views::View: + // DropdownBarView: void OnPaint(gfx::Canvas* canvas) override; void Layout() override; gfx::Size GetPreferredSize() const override; @@ -88,7 +88,8 @@ // Updates the appearance for the match count label. void UpdateMatchCountAppearance(bool no_match); - // views::View: + // DropdownBarView: + const char* GetClassName() const override; void OnThemeChanged() override; // We use a hidden view to grab mouse clicks and bring focus to the find
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc index 958dce5..ec64e54 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc
@@ -80,8 +80,10 @@ // NOTIFICATION_FULLSCREEN_CHANGED is sent asynchronously. scoped_ptr<FullscreenNotificationObserver> waiter( new FullscreenNotificationObserver()); - browser()->fullscreen_controller()->EnterFullscreenModeForTab( - web_contents, GURL()); + browser() + ->exclusive_access_manager() + ->fullscreen_controller() + ->EnterFullscreenModeForTab(web_contents, GURL()); waiter->Wait(); } EXPECT_FALSE(browser_view->immersive_mode_controller()->IsEnabled()); @@ -138,8 +140,10 @@ { scoped_ptr<FullscreenNotificationObserver> waiter( new FullscreenNotificationObserver()); - browser()->fullscreen_controller()->EnterFullscreenModeForTab( - web_contents, GURL()); + browser() + ->exclusive_access_manager() + ->fullscreen_controller() + ->EnterFullscreenModeForTab(web_contents, GURL()); waiter->Wait(); } EXPECT_TRUE(immersive_mode_controller->IsEnabled()); @@ -165,7 +169,10 @@ { scoped_ptr<FullscreenNotificationObserver> waiter( new FullscreenNotificationObserver()); - browser()->fullscreen_controller()->ExitFullscreenModeForTab(web_contents); + browser() + ->exclusive_access_manager() + ->fullscreen_controller() + ->ExitFullscreenModeForTab(web_contents); waiter->Wait(); }
diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller_ash.cc b/chrome/browser/ui/views/frame/immersive_mode_controller_ash.cc index 664a4d2..31fda808 100644 --- a/chrome/browser/ui/views/frame/immersive_mode_controller_ash.cc +++ b/chrome/browser/ui/views/frame/immersive_mode_controller_ash.cc
@@ -8,6 +8,7 @@ #include "ash/wm/immersive_revealed_lock.h" #include "ash/wm/window_state.h" #include "chrome/browser/chrome_notification_types.h" +#include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/frame/top_container_view.h" @@ -138,8 +139,9 @@ return; observers_enabled_ = enable; - content::Source<FullscreenController> source( - browser_view_->browser()->fullscreen_controller()); + content::Source<FullscreenController> source(browser_view_->browser() + ->exclusive_access_manager() + ->fullscreen_controller()); if (enable) { ash::wm::GetWindowState(native_window_)->AddObserver(this); registrar_.Add(this, chrome::NOTIFICATION_FULLSCREEN_CHANGED, source); @@ -163,8 +165,10 @@ if (!IsEnabled() || !has_tabstrip) { use_tab_indicators_ = false; } else { - bool in_tab_fullscreen = browser_view_->browser()->fullscreen_controller()-> - IsWindowFullscreenForTabOrPending(); + bool in_tab_fullscreen = browser_view_->browser() + ->exclusive_access_manager() + ->fullscreen_controller() + ->IsWindowFullscreenForTabOrPending(); use_tab_indicators_ = !in_tab_fullscreen; }
diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller_ash_unittest.cc b/chrome/browser/ui/views/frame/immersive_mode_controller_ash_unittest.cc index 85d8a0d..2a27679 100644 --- a/chrome/browser/ui/views/frame/immersive_mode_controller_ash_unittest.cc +++ b/chrome/browser/ui/views/frame/immersive_mode_controller_ash_unittest.cc
@@ -74,13 +74,16 @@ scoped_ptr<FullscreenNotificationObserver> waiter( new FullscreenNotificationObserver()); if (tab_fullscreen) { - browser()->fullscreen_controller()->EnterFullscreenModeForTab( - web_contents, GURL()); + browser() + ->exclusive_access_manager() + ->fullscreen_controller() + ->EnterFullscreenModeForTab(web_contents, GURL()); } else { - browser()->fullscreen_controller()->ExitFullscreenModeForTab( - web_contents); + browser() + ->exclusive_access_manager() + ->fullscreen_controller() + ->ExitFullscreenModeForTab(web_contents); } - waiter->Wait(); }
diff --git a/chrome/browser/ui/views/location_bar/content_setting_image_view.cc b/chrome/browser/ui/views/location_bar/content_setting_image_view.cc index 2f7459b..16cf2f9a 100644 --- a/chrome/browser/ui/views/location_bar/content_setting_image_view.cc +++ b/chrome/browser/ui/views/location_bar/content_setting_image_view.cc
@@ -187,6 +187,10 @@ height()); } +const char* ContentSettingImageView::GetClassName() const { + return "ContentSettingsImageView"; +} + bool ContentSettingImageView::OnMousePressed(const ui::MouseEvent& event) { // We want to show the bubble on mouse release; that is the standard behavior // for buttons.
diff --git a/chrome/browser/ui/views/location_bar/content_setting_image_view.h b/chrome/browser/ui/views/location_bar/content_setting_image_view.h index 5a7783d..e53de62 100644 --- a/chrome/browser/ui/views/location_bar/content_setting_image_view.h +++ b/chrome/browser/ui/views/location_bar/content_setting_image_view.h
@@ -70,6 +70,7 @@ // views::View: gfx::Size GetPreferredSize() const override; void Layout() override; + const char* GetClassName() const override; bool OnMousePressed(const ui::MouseEvent& event) override; void OnMouseReleased(const ui::MouseEvent& event) override; void OnGestureEvent(ui::GestureEvent* event) override;
diff --git a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc index 490b6be0..95fa0f0 100644 --- a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc +++ b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc
@@ -116,6 +116,10 @@ (by_icon ? 0 : LocationBarView::kIconInternalPadding); } +const char* IconLabelBubbleView::GetClassName() const { + return "IconLabelBubbleView"; +} + void IconLabelBubbleView::OnPaint(gfx::Canvas* canvas) { views::Painter* painter = (in_hover_ && hover_background_painter_) ? hover_background_painter_.get() : background_painter_.get();
diff --git a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.h b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.h index c9984ee..ac06a744 100644 --- a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.h +++ b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.h
@@ -66,6 +66,7 @@ static int GetBubbleOuterPadding(bool by_icon); // views::View: + const char* GetClassName() const override; void OnPaint(gfx::Canvas* canvas) override; int GetPreLabelWidth() const;
diff --git a/chrome/browser/ui/views/location_bar/keyword_hint_view.cc b/chrome/browser/ui/views/location_bar/keyword_hint_view.cc index e68ea89..eb28b33 100644 --- a/chrome/browser/ui/views/location_bar/keyword_hint_view.cc +++ b/chrome/browser/ui/views/location_bar/keyword_hint_view.cc
@@ -92,6 +92,10 @@ height()); } +const char* KeywordHintView::GetClassName() const { + return "KeywordHintView"; +} + views::Label* KeywordHintView::CreateLabel(const gfx::FontList& font_list, SkColor text_color, SkColor background_color) {
diff --git a/chrome/browser/ui/views/location_bar/keyword_hint_view.h b/chrome/browser/ui/views/location_bar/keyword_hint_view.h index fe27a71ec..94bdaf9 100644 --- a/chrome/browser/ui/views/location_bar/keyword_hint_view.h +++ b/chrome/browser/ui/views/location_bar/keyword_hint_view.h
@@ -41,12 +41,14 @@ void SetKeyword(const base::string16& keyword); base::string16 keyword() const { return keyword_; } + private: + // views::View: gfx::Size GetPreferredSize() const override; // The minimum size is just big enough to show the tab. gfx::Size GetMinimumSize() const override; void Layout() override; + const char* GetClassName() const override; - private: views::Label* CreateLabel(const gfx::FontList& font_list, SkColor text_color, SkColor background_color);
diff --git a/chrome/browser/ui/views/location_bar/page_action_with_badge_view.cc b/chrome/browser/ui/views/location_bar/page_action_with_badge_view.cc index 8401dc2e..3e20388 100644 --- a/chrome/browser/ui/views/location_bar/page_action_with_badge_view.cc +++ b/chrome/browser/ui/views/location_bar/page_action_with_badge_view.cc
@@ -23,6 +23,11 @@ ExtensionAction::kPageActionIconMaxSize); } +void PageActionWithBadgeView::UpdateVisibility(content::WebContents* contents) { + image_view_->UpdateVisibility(contents); + SetVisible(image_view_->visible()); +} + void PageActionWithBadgeView::Layout() { // We have 25 pixels of vertical space in the Omnibox to play with, so even // sized icons (such as 16x16) have either a 5 or a 4 pixel whitespace @@ -33,7 +38,6 @@ image_view_->SetBounds(0, y, width(), height()); } -void PageActionWithBadgeView::UpdateVisibility(content::WebContents* contents) { - image_view_->UpdateVisibility(contents); - SetVisible(image_view_->visible()); +const char* PageActionWithBadgeView::GetClassName() const { + return "PageActionWithBadgeView"; }
diff --git a/chrome/browser/ui/views/location_bar/page_action_with_badge_view.h b/chrome/browser/ui/views/location_bar/page_action_with_badge_view.h index a00d5ba..0474a7e 100644 --- a/chrome/browser/ui/views/location_bar/page_action_with_badge_view.h +++ b/chrome/browser/ui/views/location_bar/page_action_with_badge_view.h
@@ -29,7 +29,9 @@ void UpdateVisibility(content::WebContents* contents); private: + // views::View: void Layout() override; + const char* GetClassName() const override; // The button this view contains. PageActionImageView* image_view_;
diff --git a/chrome/browser/ui/views/location_bar/selected_keyword_view.cc b/chrome/browser/ui/views/location_bar/selected_keyword_view.cc index bfc76eb0f..6d0a5b24 100644 --- a/chrome/browser/ui/views/location_bar/selected_keyword_view.cc +++ b/chrome/browser/ui/views/location_bar/selected_keyword_view.cc
@@ -81,3 +81,7 @@ partial_label_.SetText(min_string.empty() ? full_label_.text() : partial_name); } + +const char* SelectedKeywordView::GetClassName() const { + return "SelectedKeywordView"; +}
diff --git a/chrome/browser/ui/views/location_bar/selected_keyword_view.h b/chrome/browser/ui/views/location_bar/selected_keyword_view.h index cba9ef934..1be64e8 100644 --- a/chrome/browser/ui/views/location_bar/selected_keyword_view.h +++ b/chrome/browser/ui/views/location_bar/selected_keyword_view.h
@@ -26,6 +26,7 @@ Profile* profile); ~SelectedKeywordView() override; + // IconLabelBubbleView: gfx::Size GetPreferredSize() const override; gfx::Size GetMinimumSize() const override; void Layout() override; @@ -35,6 +36,9 @@ const base::string16& keyword() const { return keyword_; } private: + // IconLabelBubbleView: + const char* GetClassName() const override; + // The keyword we're showing. If empty, no keyword is selected. // NOTE: we don't cache the TemplateURL as it is possible for it to get // deleted out from under us.
diff --git a/chrome/browser/ui/views/location_bar/zoom_bubble_view.cc b/chrome/browser/ui/views/location_bar/zoom_bubble_view.cc index 416de50..eff898a 100644 --- a/chrome/browser/ui/views/location_bar/zoom_bubble_view.cc +++ b/chrome/browser/ui/views/location_bar/zoom_bubble_view.cc
@@ -39,7 +39,8 @@ void ZoomBubbleView::ShowBubble(content::WebContents* web_contents, bool auto_close) { Browser* browser = chrome::FindBrowserWithWebContents(web_contents); - DCHECK(browser && browser->window() && browser->fullscreen_controller()); + DCHECK(browser && browser->window() && + browser->exclusive_access_manager()->fullscreen_controller()); BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser); bool is_fullscreen = browser_view->IsFullscreen(); @@ -66,11 +67,8 @@ // bubble must be closed and a new one created. CloseBubble(); - zoom_bubble_ = new ZoomBubbleView(anchor_view, - web_contents, - auto_close, - browser_view->immersive_mode_controller(), - browser->fullscreen_controller()); + zoom_bubble_ = new ZoomBubbleView(anchor_view, web_contents, auto_close, + browser_view->immersive_mode_controller()); // If the zoom change was initiated by an extension, capture the relevent // information from it. @@ -118,8 +116,7 @@ views::View* anchor_view, content::WebContents* web_contents, bool auto_close, - ImmersiveModeController* immersive_mode_controller, - FullscreenController* fullscreen_controller) + ImmersiveModeController* immersive_mode_controller) : ManagedFullScreenBubbleDelegateView(anchor_view, web_contents), image_button_(NULL), label_(NULL),
diff --git a/chrome/browser/ui/views/location_bar/zoom_bubble_view.h b/chrome/browser/ui/views/location_bar/zoom_bubble_view.h index 13afb64..b8039e6 100644 --- a/chrome/browser/ui/views/location_bar/zoom_bubble_view.h +++ b/chrome/browser/ui/views/location_bar/zoom_bubble_view.h
@@ -75,8 +75,7 @@ ZoomBubbleView(views::View* anchor_view, content::WebContents* web_contents, bool auto_close, - ImmersiveModeController* immersive_mode_controller, - FullscreenController* fullscreen_controller); + ImmersiveModeController* immersive_mode_controller); ~ZoomBubbleView() override; // ManagedFullScreenBubbleDelegateView:
diff --git a/chrome/browser/ui/views/location_bar/zoom_bubble_view_browsertest.cc b/chrome/browser/ui/views/location_bar/zoom_bubble_view_browsertest.cc index eaa6571..207c029 100644 --- a/chrome/browser/ui/views/location_bar/zoom_bubble_view_browsertest.cc +++ b/chrome/browser/ui/views/location_bar/zoom_bubble_view_browsertest.cc
@@ -38,8 +38,10 @@ // notification before testing the zoom bubble visibility. scoped_ptr<FullscreenNotificationObserver> waiter( new FullscreenNotificationObserver()); - browser()->fullscreen_controller()->EnterFullscreenModeForTab( - web_contents, GURL()); + browser() + ->exclusive_access_manager() + ->fullscreen_controller() + ->EnterFullscreenModeForTab(web_contents, GURL()); waiter->Wait(); } ASSERT_FALSE(browser_view->immersive_mode_controller()->IsEnabled());
diff --git a/chrome/browser/ui/views/login_view.cc b/chrome/browser/ui/views/login_view.cc index 88aa9e8b..4c97c282 100644 --- a/chrome/browser/ui/views/login_view.cc +++ b/chrome/browser/ui/views/login_view.cc
@@ -112,3 +112,8 @@ login_model_->RemoveObserver(this); login_model_ = NULL; } + +const char* LoginView::GetClassName() const { + return "LoginView"; +} +
diff --git a/chrome/browser/ui/views/login_view.h b/chrome/browser/ui/views/login_view.h index f1bc909..eab866d 100644 --- a/chrome/browser/ui/views/login_view.h +++ b/chrome/browser/ui/views/login_view.h
@@ -29,7 +29,7 @@ const base::string16& GetUsername() const; const base::string16& GetPassword() const; - // LoginModelObserver implementation. + // password_manager::LoginModelObserver: void OnAutofillDataAvailable(const base::string16& username, const base::string16& password) override; void OnLoginModelDestroying() override; @@ -38,6 +38,9 @@ views::View* GetInitiallyFocusedView(); private: + // views::View: + const char* GetClassName() const override; + // Non-owning refs to the input text fields. views::Textfield* username_field_; views::Textfield* password_field_;
diff --git a/chrome/browser/ui/views/managed_full_screen_bubble_delegate_view.cc b/chrome/browser/ui/views/managed_full_screen_bubble_delegate_view.cc index 4642cb38..9a867d2e 100644 --- a/chrome/browser/ui/views/managed_full_screen_bubble_delegate_view.cc +++ b/chrome/browser/ui/views/managed_full_screen_bubble_delegate_view.cc
@@ -21,9 +21,10 @@ // Add observer to close the bubble if the fullscreen state changes. if (web_contents) { Browser* browser = chrome::FindBrowserWithWebContents(web_contents); - registrar_.Add(this, chrome::NOTIFICATION_FULLSCREEN_CHANGED, - content::Source<FullscreenController>( - browser->fullscreen_controller())); + registrar_.Add( + this, chrome::NOTIFICATION_FULLSCREEN_CHANGED, + content::Source<FullscreenController>( + browser->exclusive_access_manager()->fullscreen_controller())); } }
diff --git a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc index e4509dd9..6c45dd4 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc
@@ -21,10 +21,14 @@ #include "ui/views/widget/widget.h" #include "ui/views/window/non_client_view.h" +namespace { + // This is the number of pixels in the border image interior to the actual // border. const int kBorderInterior = 6; +} // namespace + class OmniboxPopupContentsView::AutocompletePopupWidget : public views::Widget, public base::SupportsWeakPtr<AutocompletePopupWidget> { @@ -406,7 +410,11 @@ } //////////////////////////////////////////////////////////////////////////////// -// OmniboxPopupContentsView, views::View overrides, protected: +// OmniboxPopupContentsView, views::View overrides, private: + +const char* OmniboxPopupContentsView::GetClassName() const { + return "OmniboxPopupContentsView"; +} void OmniboxPopupContentsView::OnPaint(gfx::Canvas* canvas) { gfx::Rect contents_bounds = GetContentsBounds();
diff --git a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.h b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.h index f8130cb..09796443 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.h +++ b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.h
@@ -40,7 +40,7 @@ virtual void LayoutChildren(); - // Overridden from OmniboxPopupView: + // OmniboxPopupView: bool IsOpen() const override; void InvalidateLine(size_t line) override; void UpdatePopupAppearance() override; @@ -48,10 +48,10 @@ void PaintUpdatesNow() override; void OnDragCanceled() override; - // Overridden from gfx::AnimationDelegate: + // gfx::AnimationDelegate: void AnimationProgressed(const gfx::Animation* animation) override; - // Overridden from views::View: + // views::View: void Layout() override; views::View* GetTooltipHandlerForPoint(const gfx::Point& point) override; bool OnMousePressed(const ui::MouseEvent& event) override; @@ -61,8 +61,6 @@ void OnMouseMoved(const ui::MouseEvent& event) override; void OnMouseEntered(const ui::MouseEvent& event) override; void OnMouseExited(const ui::MouseEvent& event) override; - - // Overridden from ui::EventHandler: void OnGestureEvent(ui::GestureEvent* event) override; bool IsSelectedIndex(size_t index) const; @@ -90,7 +88,11 @@ virtual OmniboxResultView* CreateResultView(int model_index, const gfx::FontList& font_list); - // Overridden from views::View: + private: + class AutocompletePopupWidget; + + // views::View: + const char* GetClassName() const override; void OnPaint(gfx::Canvas* canvas) override; // This method should not be triggered directly as we paint our children // in an un-conventional way inside OnPaint. We use a separate canvas to @@ -99,11 +101,6 @@ void PaintChildren(gfx::Canvas* canvas, const views::CullSet& cull_set) override; - scoped_ptr<OmniboxPopupModel> model_; - - private: - class AutocompletePopupWidget; - // views::ViewTargeterDelegate: views::View* TargetForRect(views::View* root, const gfx::Rect& rect) override; @@ -137,6 +134,8 @@ OmniboxResultView* result_view_at(size_t i); + scoped_ptr<OmniboxPopupModel> model_; + // The popup that contains this view. We create this, but it deletes itself // when its window is destroyed. This is a WeakPtr because it's possible for // the OS to destroy the window and thus delete this object before we're
diff --git a/chrome/browser/ui/views/omnibox/omnibox_result_view.cc b/chrome/browser/ui/views/omnibox/omnibox_result_view.cc index 81f548db..704a01f 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_result_view.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
@@ -424,6 +424,10 @@ // static int OmniboxResultView::default_icon_size_ = 0; +const char* OmniboxResultView::GetClassName() const { + return "OmniboxResultView"; +} + gfx::ImageSkia OmniboxResultView::GetIcon() const { const gfx::Image image = model_->GetIconIfExtensionMatch(model_index_); if (!image.IsEmpty())
diff --git a/chrome/browser/ui/views/omnibox/omnibox_result_view.h b/chrome/browser/ui/views/omnibox/omnibox_result_view.h index 06bc6f2..4ce5c993 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_result_view.h +++ b/chrome/browser/ui/views/omnibox/omnibox_result_view.h
@@ -118,6 +118,9 @@ } private: + // views::View: + const char* GetClassName() const override; + gfx::ImageSkia GetIcon() const; const gfx::ImageSkia* GetKeywordIcon() const;
diff --git a/chrome/browser/ui/views/passwords/credentials_item_view.cc b/chrome/browser/ui/views/passwords/credentials_item_view.cc index a649887..8057c5b 100644 --- a/chrome/browser/ui/views/passwords/credentials_item_view.cc +++ b/chrome/browser/ui/views/passwords/credentials_item_view.cc
@@ -121,19 +121,21 @@ CredentialsItemView::CredentialsItemView( views::ButtonListener* button_listener, const autofill::PasswordForm& form, + password_manager::CredentialType credential_type, net::URLRequestContextGetter* request_context) : LabelButton(button_listener, base::string16()), form_(form), + credential_type_(credential_type), weak_ptr_factory_(this) { set_notify_enter_exit_on_child(true); // Create an image-view for the avatar. Make sure it ignores events so that // the parent can receive the events instead. image_view_ = new CircularImageView; image_view_->set_interactive(false); - gfx::Image image = - ResourceBundle::GetSharedInstance().GetImageNamed(IDR_PROFILE_AVATAR_26); - image_view_->SetImageSize(gfx::Size(kIconSize, kIconSize)); - image_view_->SetImage(image.ToImageSkia()); + gfx::Image image = ResourceBundle::GetSharedInstance().GetImageNamed( + IDR_PROFILE_AVATAR_PLACEHOLDER_LARGE); + DCHECK(image.Width() >= kIconSize && image.Height() >= kIconSize); + UpdateAvatar(image.AsImageSkia()); if (form_.avatar_url.is_valid()) { // Fetch the actual avatar. AvatarFetcher* fetcher = new AvatarFetcher(form_.avatar_url,
diff --git a/chrome/browser/ui/views/passwords/credentials_item_view.h b/chrome/browser/ui/views/passwords/credentials_item_view.h index 29bc713..0105570 100644 --- a/chrome/browser/ui/views/passwords/credentials_item_view.h +++ b/chrome/browser/ui/views/passwords/credentials_item_view.h
@@ -8,6 +8,7 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "components/autofill/core/common/password_form.h" +#include "components/password_manager/content/common/credential_manager_types.h" #include "ui/views/controls/button/label_button.h" namespace gfx { @@ -29,10 +30,14 @@ public: CredentialsItemView(views::ButtonListener* button_listener, const autofill::PasswordForm& form, + password_manager::CredentialType credential_type, net::URLRequestContextGetter* request_context); ~CredentialsItemView() override; const autofill::PasswordForm& form() const { return form_; } + password_manager::CredentialType credential_type() const { + return credential_type_; + } private: class AvatarFetcher; @@ -45,6 +50,7 @@ void UpdateAvatar(const gfx::ImageSkia& image); autofill::PasswordForm form_; + password_manager::CredentialType credential_type_; views::ImageView* image_view_; views::Label* full_name_label_;
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 b2e9413..a158ec2 100644 --- a/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc +++ b/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc
@@ -187,6 +187,12 @@ // views::ButtonListener: void ButtonPressed(views::Button* sender, const ui::Event& event) override; + // Adds |password_forms| to the layout remembering their |type|. + void AddCredentialItemsWithType( + views::GridLayout* layout, + const ScopedVector<autofill::PasswordForm>& password_forms, + password_manager::CredentialType type); + ManagePasswordsBubbleView* parent_; views::LabelButton* cancel_button_; }; @@ -208,16 +214,13 @@ BuildColumnSet(layout, SINGLE_VIEW_COLUMN_SET); AddTitleRow(layout, parent_->model()); - const auto& pending_credentials = parent_->model()->pending_credentials(); - net::URLRequestContextGetter* request_context = - parent_->model()->GetProfile()->GetRequestContext(); - for (autofill::PasswordForm* form : pending_credentials) { - CredentialsItemView* credential_view = - new CredentialsItemView(this, *form, request_context); - // Add the title to the layout with appropriate padding. - layout->StartRow(0, SINGLE_VIEW_COLUMN_SET); - layout->AddView(credential_view); - } + AddCredentialItemsWithType( + layout, parent_->model()->local_pending_credentials(), + password_manager::CredentialType::CREDENTIAL_TYPE_LOCAL); + + AddCredentialItemsWithType( + layout, parent_->model()->federated_pending_credentials(), + password_manager::CredentialType::CREDENTIAL_TYPE_FEDERATED); // Button row. BuildColumnSet(layout, SINGLE_BUTTON_COLUMN_SET); @@ -234,13 +237,28 @@ ManagePasswordsBubbleView::AccountChooserView::~AccountChooserView() { } +void ManagePasswordsBubbleView::AccountChooserView::AddCredentialItemsWithType( + views::GridLayout* layout, + const ScopedVector<autofill::PasswordForm>& password_forms, + password_manager::CredentialType type) { + net::URLRequestContextGetter* request_context = + parent_->model()->GetProfile()->GetRequestContext(); + for (autofill::PasswordForm* form : password_forms) { + // Add the title to the layout with appropriate padding. + layout->StartRow(0, SINGLE_VIEW_COLUMN_SET); + layout->AddView( + new CredentialsItemView(this, *form, type, request_context)); + } +} + void ManagePasswordsBubbleView::AccountChooserView::ButtonPressed( views::Button* sender, const ui::Event& event) { if (sender != cancel_button_) { // ManagePasswordsBubbleModel should care about calling a callback in case // the bubble is dismissed by any other means. CredentialsItemView* view = static_cast<CredentialsItemView*>(sender); - parent_->model()->OnChooseCredentials(view->form()); + parent_->model()->OnChooseCredentials(view->form(), + view->credential_type()); } else { parent_->model()->OnNopeClicked(); } @@ -843,7 +861,6 @@ Browser* browser = chrome::FindBrowserWithWebContents(web_contents); DCHECK(browser); DCHECK(browser->window()); - DCHECK(browser->fullscreen_controller()); if (IsShowing()) return;
diff --git a/chrome/browser/ui/views/profiles/user_manager_view.cc b/chrome/browser/ui/views/profiles/user_manager_view.cc index 2f9ed33..5b65703b 100644 --- a/chrome/browser/ui/views/profiles/user_manager_view.cc +++ b/chrome/browser/ui/views/profiles/user_manager_view.cc
@@ -61,13 +61,13 @@ return; } - // Create the guest profile, if necessary, and open the user manager - // from the guest profile. - profiles::CreateGuestProfileForUserManager( + // Create the system profile, if necessary, and open the user manager + // from the system profile. + profiles::CreateSystemProfileForUserManager( profile_path_to_focus, tutorial_mode, profile_open_action, - base::Bind(&UserManagerView::OnGuestProfileCreated, + base::Bind(&UserManagerView::OnSystemProfileCreated, base::Passed(make_scoped_ptr(new UserManagerView)))); } @@ -91,9 +91,9 @@ } // static -void UserManagerView::OnGuestProfileCreated( +void UserManagerView::OnSystemProfileCreated( scoped_ptr<UserManagerView> instance, - Profile* guest_profile, + Profile* system_profile, const std::string& url) { // If we are showing the User Manager after locking a profile, change the // active profile to Guest. @@ -101,11 +101,11 @@ DCHECK(!instance_); instance_ = instance.release(); // |instance_| takes over ownership. - instance_->Init(guest_profile, GURL(url)); + instance_->Init(system_profile, GURL(url)); } -void UserManagerView::Init(Profile* guest_profile, const GURL& url) { - web_view_ = new views::WebView(guest_profile); +void UserManagerView::Init(Profile* system_profile, const GURL& url) { + web_view_ = new views::WebView(system_profile); web_view_->set_allow_accelerators(true); AddChildView(web_view_); SetLayoutManager(new views::FillLayout); @@ -149,7 +149,7 @@ // Set the app id for the task manager to the app id of its parent ui::win::SetAppIdForWindow( ShellIntegration::GetChromiumModelIdForProfile( - guest_profile->GetPath()), + system_profile->GetPath()), views::HWNDForWidget(GetWidget())); #endif
diff --git a/chrome/browser/ui/views/profiles/user_manager_view.h b/chrome/browser/ui/views/profiles/user_manager_view.h index aca84804..11fc1ff 100644 --- a/chrome/browser/ui/views/profiles/user_manager_view.h +++ b/chrome/browser/ui/views/profiles/user_manager_view.h
@@ -22,11 +22,11 @@ // Do not call directly. To display the User Manager, use UserManager::Show(). UserManagerView(); - // Creates a new UserManagerView instance for the |guest_profile| and - // shows the |url|. - static void OnGuestProfileCreated(scoped_ptr<UserManagerView> instance, - Profile* guest_profile, - const std::string& url); + // Creates a new UserManagerView instance for the |system_profile| and shows + // the |url|. + static void OnSystemProfileCreated(scoped_ptr<UserManagerView> instance, + Profile* system_profile, + const std::string& url); private: ~UserManagerView() override;
diff --git a/chrome/browser/ui/views/status_bubble_views.cc b/chrome/browser/ui/views/status_bubble_views.cc index bec9e6052..a6ca0372 100644 --- a/chrome/browser/ui/views/status_bubble_views.cc +++ b/chrome/browser/ui/views/status_bubble_views.cc
@@ -168,6 +168,7 @@ void StartShowing(); // views::View: + const char* GetClassName() const override; void OnPaint(gfx::Canvas* canvas) override; BubbleState state_; @@ -350,6 +351,10 @@ } } +const char* StatusBubbleViews::StatusView::GetClassName() const { + return "StatusBubbleViews::StatusView"; +} + void StatusBubbleViews::StatusView::OnPaint(gfx::Canvas* canvas) { SkPaint paint; paint.setStyle(SkPaint::kFill_Style);
diff --git a/chrome/browser/ui/views/tab_icon_view.cc b/chrome/browser/ui/views/tab_icon_view.cc index 400c7e4..bf9110d 100644 --- a/chrome/browser/ui/views/tab_icon_view.cc +++ b/chrome/browser/ui/views/tab_icon_view.cc
@@ -25,8 +25,12 @@ #include "ui/gfx/icon_util.h" #endif -static bool g_initialized = false; -static gfx::ImageSkia* g_default_favicon = NULL; +namespace { + +bool g_initialized = false; +gfx::ImageSkia* g_default_favicon = nullptr; + +} // namespace // static void TabIconView::InitializeIfNeeded() { @@ -137,6 +141,14 @@ dest_h, filter); } +gfx::Size TabIconView::GetPreferredSize() const { + return gfx::Size(gfx::kFaviconSize, gfx::kFaviconSize); +} + +const char* TabIconView::GetClassName() const { + return "TabIconView"; +} + void TabIconView::OnPaint(gfx::Canvas* canvas) { bool rendered = false; @@ -154,7 +166,3 @@ if (!rendered) PaintFavicon(canvas, *g_default_favicon); } - -gfx::Size TabIconView::GetPreferredSize() const { - return gfx::Size(gfx::kFaviconSize, gfx::kFaviconSize); -}
diff --git a/chrome/browser/ui/views/tab_icon_view.h b/chrome/browser/ui/views/tab_icon_view.h index f3b2da2..4f3d722 100644 --- a/chrome/browser/ui/views/tab_icon_view.h +++ b/chrome/browser/ui/views/tab_icon_view.h
@@ -33,11 +33,12 @@ // Set the throbber to the light style (for use on dark backgrounds). void set_is_light(bool is_light) { is_light_ = is_light; } - // Overridden from View - void OnPaint(gfx::Canvas* canvas) override; - gfx::Size GetPreferredSize() const override; - private: + // views::MenuButton: + gfx::Size GetPreferredSize() const override; + const char* GetClassName() const override; + void OnPaint(gfx::Canvas* canvas) override; + void PaintThrobber(gfx::Canvas* canvas); void PaintFavicon(gfx::Canvas* canvas, const gfx::ImageSkia& image); void PaintIcon(gfx::Canvas* canvas,
diff --git a/chrome/browser/ui/views/toolbar/back_button.cc b/chrome/browser/ui/views/toolbar/back_button.cc index 1bfc7431..54c6f2f9 100644 --- a/chrome/browser/ui/views/toolbar/back_button.cc +++ b/chrome/browser/ui/views/toolbar/back_button.cc
@@ -15,12 +15,6 @@ BackButton::~BackButton() {} -gfx::Rect BackButton::GetThemePaintRect() const { - gfx::Rect rect(LabelButton::GetThemePaintRect()); - rect.Inset(margin_leading_, 0, 0, 0); - return rect; -} - void BackButton::SetLeadingMargin(int margin) { margin_leading_ = margin; @@ -37,6 +31,10 @@ InvalidateLayout(); } +const char* BackButton::GetClassName() const { + return "BackButton"; +} + scoped_ptr<views::LabelButtonBorder> BackButton::CreateDefaultBorder() const { scoped_ptr<views::LabelButtonBorder> border = ToolbarButton::CreateDefaultBorder(); @@ -50,3 +48,10 @@ return border.Pass(); } + +gfx::Rect BackButton::GetThemePaintRect() const { + gfx::Rect rect(LabelButton::GetThemePaintRect()); + rect.Inset(margin_leading_, 0, 0, 0); + return rect; +} +
diff --git a/chrome/browser/ui/views/toolbar/back_button.h b/chrome/browser/ui/views/toolbar/back_button.h index ad37dc29..6383b26 100644 --- a/chrome/browser/ui/views/toolbar/back_button.h +++ b/chrome/browser/ui/views/toolbar/back_button.h
@@ -29,11 +29,12 @@ void SetLeadingMargin(int margin); - protected: - gfx::Rect GetThemePaintRect() const override; - scoped_ptr<views::LabelButtonBorder> CreateDefaultBorder() const override; - private: + // ToolbarButton: + const char* GetClassName() const override; + scoped_ptr<views::LabelButtonBorder> CreateDefaultBorder() const override; + gfx::Rect GetThemePaintRect() const override; + // Any leading margin to be applied. Used when the back button is in // a maximized state to extend to the full window width. int margin_leading_;
diff --git a/chrome/browser/ui/views/toolbar/home_button.cc b/chrome/browser/ui/views/toolbar/home_button.cc index 39db820..db8c654 100644 --- a/chrome/browser/ui/views/toolbar/home_button.cc +++ b/chrome/browser/ui/views/toolbar/home_button.cc
@@ -146,6 +146,10 @@ HomeButton::~HomeButton() { } +const char* HomeButton::GetClassName() const { + return "HomeButton"; +} + bool HomeButton::GetDropFormats( int* formats, std::set<OSExchangeData::CustomFormat>* custom_formats) {
diff --git a/chrome/browser/ui/views/toolbar/home_button.h b/chrome/browser/ui/views/toolbar/home_button.h index 05fd0fdb..b6c236d7a 100644 --- a/chrome/browser/ui/views/toolbar/home_button.h +++ b/chrome/browser/ui/views/toolbar/home_button.h
@@ -16,7 +16,9 @@ HomeButton(views::ButtonListener* listener, Browser* browser); ~HomeButton() override; + private: // ToolbarButton: + const char* GetClassName() const override; bool GetDropFormats( int* formats, std::set<OSExchangeData::CustomFormat>* custom_formats) override; @@ -24,7 +26,6 @@ int OnDragUpdated(const ui::DropTargetEvent& event) override; int OnPerformDrop(const ui::DropTargetEvent& event) override; - private: // ToolbarButton: void NotifyClick(const ui::Event& event) override;
diff --git a/chrome/browser/ui/views/toolbar/toolbar_action_view.cc b/chrome/browser/ui/views/toolbar/toolbar_action_view.cc index 5046166..7ee1abb 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_action_view.cc +++ b/chrome/browser/ui/views/toolbar/toolbar_action_view.cc
@@ -86,6 +86,20 @@ views::Painter::CreateImageGridPainter(kRaisedImages)); } +gfx::Size ToolbarActionView::GetPreferredSize() const { + return gfx::Size(ToolbarActionsBar::IconWidth(false), + ToolbarActionsBar::IconHeight()); +} + +const char* ToolbarActionView::GetClassName() const { + return "ToolbarActionView"; +} + +void ToolbarActionView::OnDragDone() { + views::MenuButton::OnDragDone(); + delegate_->OnToolbarActionViewDragDone(); +} + void ToolbarActionView::ViewHierarchyChanged( const ViewHierarchyChangedDetails& details) { if (details.is_add && !called_register_command_ && GetFocusManager()) { @@ -96,16 +110,6 @@ MenuButton::ViewHierarchyChanged(details); } -void ToolbarActionView::OnDragDone() { - views::MenuButton::OnDragDone(); - delegate_->OnToolbarActionViewDragDone(); -} - -gfx::Size ToolbarActionView::GetPreferredSize() const { - return gfx::Size(ToolbarActionsBar::IconWidth(false), - ToolbarActionsBar::IconHeight()); -} - void ToolbarActionView::PaintChildren(gfx::Canvas* canvas, const views::CullSet& cull_set) { View::PaintChildren(canvas, cull_set);
diff --git a/chrome/browser/ui/views/toolbar/toolbar_action_view.h b/chrome/browser/ui/views/toolbar/toolbar_action_view.h index f5aad22b..d19c94ac 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_action_view.h +++ b/chrome/browser/ui/views/toolbar/toolbar_action_view.h
@@ -74,13 +74,13 @@ // an action wants to run. static void DecorateWantsToRunBorder(views::LabelButtonBorder* border); - // Overridden from views::View: + // views::MenuButton: void GetAccessibleState(ui::AXViewState* state) override; - // Overridden from views::ButtonListener: + // views::ButtonListener: void ButtonPressed(views::Button* sender, const ui::Event& event) override; - // Overridden from content::NotificationObserver: + // content::NotificationObserver: void Observe(int type, const content::NotificationSource& source, const content::NotificationDetails& details) override; @@ -113,11 +113,12 @@ bool wants_to_run_for_testing() const { return wants_to_run_; } private: - // Overridden from views::View: + // views::MenuButton: + gfx::Size GetPreferredSize() const override; + const char* GetClassName() const override; + void OnDragDone() override; void ViewHierarchyChanged( const ViewHierarchyChangedDetails& details) override; - void OnDragDone() override; - gfx::Size GetPreferredSize() const override; void PaintChildren(gfx::Canvas* canvas, const views::CullSet& cull_set) override; void OnPaintBorder(gfx::Canvas* canvas) override;
diff --git a/chrome/browser/ui/views/toolbar/toolbar_button.cc b/chrome/browser/ui/views/toolbar/toolbar_button.cc index 8e2d92c..2bd587a 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_button.cc +++ b/chrome/browser/ui/views/toolbar/toolbar_button.cc
@@ -248,3 +248,7 @@ if (state_ != STATE_DISABLED) SetState(STATE_NORMAL); } + +const char* ToolbarButton::GetClassName() const { + return "ToolbarButton"; +}
diff --git a/chrome/browser/ui/views/toolbar/toolbar_button.h b/chrome/browser/ui/views/toolbar/toolbar_button.h index ad52183..ebc113a 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_button.h +++ b/chrome/browser/ui/views/toolbar/toolbar_button.h
@@ -66,6 +66,9 @@ virtual void ShowDropDownMenu(ui::MenuSourceType source_type); private: + // views::LabelButton: + const char* GetClassName() const override; + // The model that populates the attached menu. scoped_ptr<ui::MenuModel> model_;
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.h b/chrome/browser/ui/views/toolbar/toolbar_view.h index b5e63b8..32fe3f6 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_view.h +++ b/chrome/browser/ui/views/toolbar/toolbar_view.h
@@ -5,9 +5,6 @@ #ifndef CHROME_BROWSER_UI_VIEWS_TOOLBAR_TOOLBAR_VIEW_H_ #define CHROME_BROWSER_UI_VIEWS_TOOLBAR_TOOLBAR_VIEW_H_ -#include <set> -#include <string> - #include "base/memory/scoped_ptr.h" #include "base/observer_list.h" #include "base/prefs/pref_member.h"
diff --git a/chrome/browser/ui/views/toolbar/wrench_toolbar_button.cc b/chrome/browser/ui/views/toolbar/wrench_toolbar_button.cc index 9f8c8ea..ef221ee 100644 --- a/chrome/browser/ui/views/toolbar/wrench_toolbar_button.cc +++ b/chrome/browser/ui/views/toolbar/wrench_toolbar_button.cc
@@ -58,18 +58,14 @@ GetImageSkiaNamed(IDR_TOOLBAR_BEZEL_HOVER)->size(); } -void WrenchToolbarButton::OnPaint(gfx::Canvas* canvas) { - views::MenuButton::OnPaint(canvas); - wrench_icon_painter_->Paint(canvas, - GetThemeProvider(), - gfx::Rect(size()), - WrenchIconPainter::BEZEL_NONE); -} - void WrenchToolbarButton::ScheduleWrenchIconPaint() { SchedulePaint(); } +const char* WrenchToolbarButton::GetClassName() const { + return "WrenchToolbarButton"; +} + bool WrenchToolbarButton::GetDropFormats( int* formats, std::set<ui::OSExchangeData::CustomFormat>* custom_formats) { return allow_extension_dragging_ ? @@ -117,6 +113,14 @@ return ui::DragDropTypes::DRAG_MOVE; } +void WrenchToolbarButton::OnPaint(gfx::Canvas* canvas) { + views::MenuButton::OnPaint(canvas); + wrench_icon_painter_->Paint(canvas, + GetThemeProvider(), + gfx::Rect(size()), + WrenchIconPainter::BEZEL_NONE); +} + void WrenchToolbarButton::ShowOverflowMenu() { toolbar_view_->ShowAppMenu(true); // For drop. }
diff --git a/chrome/browser/ui/views/toolbar/wrench_toolbar_button.h b/chrome/browser/ui/views/toolbar/wrench_toolbar_button.h index 5321ddf..3e99ecd 100644 --- a/chrome/browser/ui/views/toolbar/wrench_toolbar_button.h +++ b/chrome/browser/ui/views/toolbar/wrench_toolbar_button.h
@@ -28,7 +28,6 @@ // views::MenuButton: gfx::Size GetPreferredSize() const override; - void OnPaint(gfx::Canvas* canvas) override; // WrenchIconPainter::Delegate: void ScheduleWrenchIconPaint() override; @@ -45,7 +44,8 @@ static bool g_open_wrench_immediately_for_testing; private: - // views::View: + // views::MenuButton: + const char* GetClassName() const override; bool GetDropFormats( int* formats, std::set<ui::OSExchangeData::CustomFormat>* custom_formats) override; @@ -55,6 +55,7 @@ int OnDragUpdated(const ui::DropTargetEvent& event) override; void OnDragExited() override; int OnPerformDrop(const ui::DropTargetEvent& event) override; + void OnPaint(gfx::Canvas* canvas) override; // Show the extension action overflow menu (which is in the app menu). void ShowOverflowMenu();
diff --git a/chrome/browser/ui/views/website_settings/permissions_bubble_view.cc b/chrome/browser/ui/views/website_settings/permissions_bubble_view.cc index d0ef412..ae41cd1 100644 --- a/chrome/browser/ui/views/website_settings/permissions_bubble_view.cc +++ b/chrome/browser/ui/views/website_settings/permissions_bubble_view.cc
@@ -263,6 +263,7 @@ views::ImageView* icon = new views::ImageView(); icon->SetImage(bundle.GetImageSkiaNamed(requests.at(index)->GetIconID())); icon->SetImageSize(gfx::Size(kIconSize, kIconSize)); + icon->SetTooltipText(base::string16()); // Redundant with the text fragment label_container->AddChildView(icon); views::Label* label = new views::Label(requests.at(index)->GetMessageTextFragment()); @@ -330,6 +331,8 @@ new CustomizeAllowComboboxModel()); allow_combobox->set_listener(this); allow_combobox->SetStyle(views::Combobox::STYLE_ACTION); + allow_combobox->SetAccessibleName( + l10n_util::GetStringUTF16(IDS_PERMISSION_ALLOW_COMBOBOX)); button_layout->AddView(allow_combobox); allow_combobox_ = allow_combobox; }
diff --git a/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc b/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc index ea8ed29..2c9dad3 100644 --- a/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc
@@ -321,6 +321,11 @@ UpdateOobeUIVisibility(); } +void CoreOobeHandler::UpdateShutdownAndRebootVisibility( + bool reboot_on_shutdown) { + CallJS("showShutdown", !reboot_on_shutdown); +} + void CoreOobeHandler::UpdateA11yState() { // TODO(dpolukhin): crbug.com/412891 DCHECK(MagnificationManager::Get());
diff --git a/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.h b/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.h index 405c0a9..1fcccdd 100644 --- a/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.h +++ b/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.h
@@ -61,6 +61,11 @@ return show_oobe_ui_; } + // If |reboot_on_shutdown| is true, the reboot button becomes visible + // and the shutdown button is hidden. Vice versa if |reboot_on_shutdown| is + // false. + void UpdateShutdownAndRebootVisibility(bool reboot_on_shutdown); + private: // CoreOobeActor implementation: void ShowSignInError(int login_attempts,
diff --git a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc index 8270242c..80c8e2f8e 100644 --- a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc +++ b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
@@ -6,6 +6,7 @@ #include "base/command_line.h" #include "base/logging.h" +#include "base/memory/scoped_ptr.h" #include "base/strings/stringprintf.h" #include "base/values.h" #include "chrome/browser/browser_process.h" @@ -19,6 +20,7 @@ #include "chrome/browser/chromeos/login/wizard_controller.h" #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" #include "chrome/browser/chromeos/policy/consumer_management_service.h" +#include "chrome/browser/chromeos/settings/shutdown_policy_handler.h" #include "chrome/browser/chromeos/system/input_device_settings.h" #include "chrome/browser/extensions/signin/gaia_auth_extension_loader.h" #include "chrome/browser/extensions/tab_helper.h" @@ -484,6 +486,10 @@ return user_board_screen_handler_; } +void OobeUI::OnShutdownPolicyChanged(bool reboot_on_shutdown) { + core_handler_->UpdateShutdownAndRebootVisibility(reboot_on_shutdown); +} + AppLaunchSplashScreenActor* OobeUI::GetAppLaunchSplashScreenActor() { return app_launch_splash_screen_actor_; @@ -570,6 +576,14 @@ if (handlers_[i]->async_assets_load_id().empty()) handlers_[i]->InitializeBase(); } + + // Instantiate the ShutdownPolicyHandler. + shutdown_policy_handler_.reset( + new ShutdownPolicyHandler(CrosSettings::Get(), this)); + + // Trigger an initial update. + shutdown_policy_handler_->CheckIfRebootOnShutdown( + base::Bind(&OobeUI::OnShutdownPolicyChanged, base::Unretained(this))); } void OobeUI::OnScreenAssetsLoaded(const std::string& async_assets_load_id) {
diff --git a/chrome/browser/ui/webui/chromeos/login/oobe_ui.h b/chrome/browser/ui/webui/chromeos/login/oobe_ui.h index c14c91f5..02085325 100644 --- a/chrome/browser/ui/webui/chromeos/login/oobe_ui.h +++ b/chrome/browser/ui/webui/chromeos/login/oobe_ui.h
@@ -14,6 +14,7 @@ #include "base/memory/scoped_ptr.h" #include "base/observer_list.h" #include "chrome/browser/chromeos/login/ui/oobe_display.h" +#include "chrome/browser/chromeos/settings/shutdown_policy_handler.h" #include "chrome/browser/ui/webui/chromeos/login/core_oobe_handler.h" #include "content/public/browser/web_ui_controller.h" @@ -47,7 +48,8 @@ // - update screen. class OobeUI : public OobeDisplay, public content::WebUIController, - public CoreOobeHandler::Delegate { + public CoreOobeHandler::Delegate, + public ShutdownPolicyHandler::Delegate { public: class Observer { public: @@ -122,6 +124,9 @@ GaiaScreenHandler* GetGaiaScreenActor() override; UserBoardView* GetUserBoardScreenActor() override; + // ShutdownPolicyObserver::Delegate + void OnShutdownPolicyChanged(bool reboot_on_shutdown) override; + // Collects localized strings from the owned handlers. void GetLocalizedStrings(base::DictionaryValue* localized_strings); @@ -248,6 +253,9 @@ // List of registered observers. ObserverList<Observer> observer_list_; + // Observer of CrosSettings watching the kRebootOnShutdown policy. + scoped_ptr<ShutdownPolicyHandler> shutdown_policy_handler_; + DISALLOW_COPY_AND_ASSIGN(OobeUI); };
diff --git a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc index 001b49a9..b532c2c98 100644 --- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
@@ -365,6 +365,7 @@ builder->Add("signedIn", IDS_SCREEN_LOCK_ACTIVE_USER); builder->Add("signinButton", IDS_LOGIN_BUTTON); builder->Add("launchAppButton", IDS_LAUNCH_APP_BUTTON); + builder->Add("restart", IDS_RESTART_BUTTON); builder->Add("shutDown", IDS_SHUTDOWN_BUTTON); builder->Add("addUser", IDS_ADD_USER_BUTTON); builder->Add("browseAsGuest", IDS_GO_INCOGNITO_BUTTON);
diff --git a/chrome/browser/ui/webui/components_ui.cc b/chrome/browser/ui/webui/components_ui.cc index 46536e1d..50248cc5 100644 --- a/chrome/browser/ui/webui/components_ui.cc +++ b/chrome/browser/ui/webui/components_ui.cc
@@ -16,7 +16,6 @@ #include "chrome/common/url_constants.h" #include "chrome/grit/generated_resources.h" #include "components/component_updater/component_updater_service.h" -#include "components/component_updater/crx_update_item.h" #include "content/public/browser/web_ui.h" #include "content/public/browser/web_ui_data_source.h" #include "content/public/browser/web_ui_message_handler.h" @@ -167,7 +166,7 @@ // Construct DictionaryValues to return to UI. base::ListValue* component_list = new base::ListValue(); for (size_t j = 0; j < component_ids.size(); ++j) { - component_updater::CrxUpdateItem item; + update_client::CrxUpdateItem item; if (cus->GetComponentDetails(component_ids[j], &item)) { base::DictionaryValue* component_entry = new base::DictionaryValue(); component_entry->SetString("id", component_ids[j]); @@ -209,29 +208,29 @@ } base::string16 ComponentsUI::ServiceStatusToString( - component_updater::CrxUpdateItem::Status status) { + update_client::CrxUpdateItem::Status status) { switch (status) { - case component_updater::CrxUpdateItem::kNew: + case update_client::CrxUpdateItem::kNew: return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_NEW); - case component_updater::CrxUpdateItem::kChecking: + case update_client::CrxUpdateItem::kChecking: return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_CHECKING); - case component_updater::CrxUpdateItem::kCanUpdate: + case update_client::CrxUpdateItem::kCanUpdate: return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_UPDATE); - case component_updater::CrxUpdateItem::kDownloadingDiff: + case update_client::CrxUpdateItem::kDownloadingDiff: return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_DNL_DIFF); - case component_updater::CrxUpdateItem::kDownloading: + case update_client::CrxUpdateItem::kDownloading: return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_DNL); - case component_updater::CrxUpdateItem::kUpdatingDiff: + case update_client::CrxUpdateItem::kUpdatingDiff: return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_UPDT_DIFF); - case component_updater::CrxUpdateItem::kUpdating: + case update_client::CrxUpdateItem::kUpdating: return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_UPDATING); - case component_updater::CrxUpdateItem::kUpdated: + case update_client::CrxUpdateItem::kUpdated: return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_UPDATED); - case component_updater::CrxUpdateItem::kUpToDate: + case update_client::CrxUpdateItem::kUpToDate: return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_UPTODATE); - case component_updater::CrxUpdateItem::kNoUpdate: + case update_client::CrxUpdateItem::kNoUpdate: return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_NOUPDATE); - case component_updater::CrxUpdateItem::kLastStatus: + case update_client::CrxUpdateItem::kLastStatus: return l10n_util::GetStringUTF16(IDS_COMPONENTS_UNKNOWN); } return l10n_util::GetStringUTF16(IDS_COMPONENTS_UNKNOWN); @@ -244,7 +243,7 @@ using component_updater::ComponentUpdateService; if (event == ComponentUpdateService::Observer::COMPONENT_UPDATED) { ComponentUpdateService* cus = g_browser_process->component_updater(); - component_updater::CrxUpdateItem item; + update_client::CrxUpdateItem item; if (cus->GetComponentDetails(id, &item)) parameters.SetString("version", item.component.version.GetString()); }
diff --git a/chrome/browser/ui/webui/components_ui.h b/chrome/browser/ui/webui/components_ui.h index d92279e..21c702f2 100644 --- a/chrome/browser/ui/webui/components_ui.h +++ b/chrome/browser/ui/webui/components_ui.h
@@ -5,8 +5,10 @@ #ifndef CHROME_BROWSER_UI_WEBUI_COMPONENTS_UI_H_ #define CHROME_BROWSER_UI_WEBUI_COMPONENTS_UI_H_ +#include <string> + #include "components/component_updater/component_updater_service.h" -#include "components/component_updater/crx_update_item.h" +#include "components/update_client/crx_update_item.h" #include "content/public/browser/web_ui_controller.h" #include "ui/base/layout.h" @@ -37,7 +39,7 @@ private: static base::string16 ComponentEventToString(Events event); static base::string16 ServiceStatusToString( - component_updater::CrxUpdateItem::Status status); + update_client::CrxUpdateItem::Status status); DISALLOW_COPY_AND_ASSIGN(ComponentsUI); };
diff --git a/chrome/browser/ui/webui/extensions/extension_settings_browsertest.js b/chrome/browser/ui/webui/extensions/extension_settings_browsertest.js index 98ef6a75..3ae8df0 100644 --- a/chrome/browser/ui/webui/extensions/extension_settings_browsertest.js +++ b/chrome/browser/ui/webui/extensions/extension_settings_browsertest.js
@@ -89,7 +89,7 @@ testDone(); } }); - ensureTransitionEndEvent(devControl, 500); + ensureTransitionEndEvent(devControl, 4000); }); /**
diff --git a/chrome/browser/ui/webui/local_discovery/local_discovery_ui_handler.cc b/chrome/browser/ui/webui/local_discovery/local_discovery_ui_handler.cc index 3fd74d6..e1a3dac 100644 --- a/chrome/browser/ui/webui/local_discovery/local_discovery_ui_handler.cc +++ b/chrome/browser/ui/webui/local_discovery/local_discovery_ui_handler.cc
@@ -10,39 +10,30 @@ #include "base/command_line.h" #include "base/message_loop/message_loop.h" #include "base/prefs/pref_service.h" -#include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" +#include "chrome/browser/local_discovery/cloud_device_list.h" #include "chrome/browser/local_discovery/privet_confirm_api_flow.h" #include "chrome/browser/local_discovery/privet_constants.h" #include "chrome/browser/local_discovery/privet_device_lister_impl.h" #include "chrome/browser/local_discovery/privet_http_asynchronous_factory.h" -#include "chrome/browser/local_discovery/privet_http_impl.h" #include "chrome/browser/local_discovery/service_discovery_shared_client.h" #include "chrome/browser/printing/cloud_print/cloud_print_proxy_service.h" #include "chrome/browser/printing/cloud_print/cloud_print_proxy_service_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" #include "chrome/browser/signin/signin_manager_factory.h" -#include "chrome/browser/signin/signin_promo.h" #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/browser_tabstrip.h" #include "chrome/browser/ui/chrome_pages.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" #include "chrome/grit/generated_resources.h" -#include "components/cloud_devices/common/cloud_devices_switches.h" #include "components/cloud_devices/common/cloud_devices_urls.h" #include "components/signin/core/browser/profile_oauth2_token_service.h" -#include "components/signin/core/browser/signin_manager_base.h" #include "content/public/browser/user_metrics.h" #include "content/public/browser/web_ui.h" -#include "net/base/host_port_pair.h" -#include "net/base/net_util.h" -#include "net/base/url_util.h" -#include "net/http/http_status_code.h" #include "ui/base/l10n/l10n_util.h" -#include "ui/base/page_transition_types.h" #if defined(ENABLE_PRINT_PREVIEW) && !defined(OS_CHROMEOS) #define CLOUD_PRINT_CONNECTOR_UI_AVAILABLE @@ -61,10 +52,6 @@ const char kKeyPrefixMDns[] = "MDns:"; -#if defined(ENABLE_WIFI_BOOTSTRAPPING) -const char kKeyPrefixWifi[] = "WiFi:"; -#endif // ENABLE_WIFI_BOOTSTRAPPING - int g_num_visible = 0; const int kCloudDevicesPrivetVersion = 3; @@ -145,10 +132,6 @@ web_ui()->RegisterMessageCallback("registerDevice", base::Bind( &LocalDiscoveryUIHandler::HandleRegisterDevice, base::Unretained(this))); - web_ui()->RegisterMessageCallback( - "confirmCode", - base::Bind(&LocalDiscoveryUIHandler::HandleConfirmCode, - base::Unretained(this))); web_ui()->RegisterMessageCallback("cancelRegistration", base::Bind( &LocalDiscoveryUIHandler::HandleCancelRegistration, base::Unretained(this))); @@ -203,13 +186,6 @@ StartCloudPrintConnector(); #endif -#if defined(ENABLE_WIFI_BOOTSTRAPPING) - if (base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableCloudDevices)) { - StartWifiBootstrapping(); - } -#endif - CheckUserLoggedIn(); } @@ -233,10 +209,7 @@ return; } - if (found->second.version == kCloudDevicesPrivetVersion) { - current_setup_operation_.reset(new PrivetV3SetupFlow(this)); - current_setup_operation_->Register(device); - } else if (found->second.version <= 2) { + if (found->second.version < kCloudDevicesPrivetVersion) { privet_resolution_ = privet_http_factory_->CreatePrivetHTTP( device, found->second.address, @@ -248,10 +221,6 @@ } } -void LocalDiscoveryUIHandler::HandleConfirmCode(const base::ListValue* args) { - device_code_callback_.Run(true); -} - void LocalDiscoveryUIHandler::HandleCancelRegistration( const base::ListValue* args) { ResetCurrentRegistration(); @@ -263,20 +232,11 @@ succeded_list_count_ = 0; cloud_devices_.clear(); - cloud_print_printer_list_ = CreateApiFlow(); - if (base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableCloudDevices)) { - cloud_device_list_ = CreateApiFlow(); - } - if (cloud_print_printer_list_) { cloud_print_printer_list_->Start( make_scoped_ptr<GCDApiFlow::Request>(new CloudPrintPrinterList(this))); } - if (cloud_device_list_) { - cloud_device_list_->Start( - make_scoped_ptr<GCDApiFlow::Request>(new CloudDeviceList(this))); - } + CheckListingDone(); } @@ -370,42 +330,11 @@ PrivetRegisterOperation* operation, const std::string& device_id) { std::string name = operation->GetHTTPClient()->GetName(); - current_setup_operation_.reset(); current_register_operation_.reset(); current_http_client_.reset(); SendRegisterDone(name); } -void LocalDiscoveryUIHandler::GetWiFiCredentials( - const CredentialsCallback& callback) { - callback.Run("", ""); -} - -void LocalDiscoveryUIHandler::SwitchToSetupWiFi( - const ResultCallback& callback) { - callback.Run(true); -} - -void LocalDiscoveryUIHandler::ConfirmSecurityCode( - const ResultCallback& callback) { - device_code_callback_ = callback; - web_ui()->CallJavascriptFunction( - "local_discovery.onRegistrationConfirmDeviceCode", - base::StringValue("1234")); -} - -void LocalDiscoveryUIHandler::RestoreWifi(const ResultCallback& callback) { - callback.Run(true); -} - -void LocalDiscoveryUIHandler::OnSetupDone() { - std::string service_name = current_setup_operation_->service_name(); - current_setup_operation_.reset(); - current_register_operation_.reset(); - current_http_client_.reset(); - SendRegisterDone(service_name); -} - void LocalDiscoveryUIHandler::OnSetupError() { ResetCurrentRegistration(); SendRegisterError(); @@ -544,18 +473,11 @@ current_register_operation_.reset(); } - current_setup_operation_.reset(); confirm_api_call_flow_.reset(); privet_resolution_.reset(); current_http_client_.reset(); } -void LocalDiscoveryUIHandler::PrivetClientToV3( - const PrivetClientCallback& callback, - scoped_ptr<PrivetHTTPClient> client) { - callback.Run(client.Pass()); -} - void LocalDiscoveryUIHandler::CheckUserLoggedIn() { base::FundamentalValue logged_in_value(!GetSyncAccount().empty()); base::FundamentalValue is_supervised_value(IsUserSupervisedOrOffTheRecord()); @@ -567,8 +489,6 @@ int started = 0; if (cloud_print_printer_list_) ++started; - if (cloud_device_list_) - ++started; if (started > failed_list_count_ + succeded_list_count_) return; @@ -592,7 +512,6 @@ web_ui()->CallJavascriptFunction( "local_discovery.onCloudDeviceListAvailable", devices_list); cloud_print_printer_list_.reset(); - cloud_device_list_.reset(); } scoped_ptr<GCDApiFlow> LocalDiscoveryUIHandler::CreateApiFlow() { @@ -612,25 +531,6 @@ signin_manager->GetAuthenticatedAccountId()); } -void LocalDiscoveryUIHandler::CreatePrivetV3Client( - const std::string& device, - const PrivetClientCallback& callback) { - DeviceDescriptionMap::iterator found = device_descriptions_.find(device); - if (found == device_descriptions_.end()) - return callback.Run(scoped_ptr<PrivetHTTPClient>()); - PrivetHTTPAsynchronousFactory::ResultCallback new_callback = - base::Bind(&LocalDiscoveryUIHandler::PrivetClientToV3, - base::Unretained(this), - callback); - privet_resolution_ = - privet_http_factory_->CreatePrivetHTTP(device, - found->second.address, - new_callback).Pass(); - if (!privet_resolution_) - return callback.Run(scoped_ptr<PrivetHTTPClient>()); - privet_resolution_->Start(); -} - bool LocalDiscoveryUIHandler::IsUserSupervisedOrOffTheRecord() { Profile* profile = Profile::FromWebUI(web_ui()); @@ -745,49 +645,4 @@ #endif // cloud print connector option stuff -#if defined(ENABLE_WIFI_BOOTSTRAPPING) - -void LocalDiscoveryUIHandler::StartWifiBootstrapping() { - // Since LocalDiscoveryUIHandler isn't destroyed every time the page is - // refreshed, reset bootstrapping_device_lister_ so it's destoryed before - // wifi_manager_ is. - bootstrapping_device_lister_.reset(); - - wifi_manager_ = wifi::WifiManager::Create(); - bootstrapping_device_lister_.reset(new wifi::BootstrappingDeviceLister( - wifi_manager_.get(), - base::Bind(&LocalDiscoveryUIHandler::OnBootstrappingDeviceChanged, - base::Unretained(this)))); - - wifi_manager_->Start(); - bootstrapping_device_lister_->Start(); - wifi_manager_->RequestScan(); -} - -void LocalDiscoveryUIHandler::OnBootstrappingDeviceChanged( - bool available, - const wifi::BootstrappingDeviceDescription& description) { - base::DictionaryValue info; - - base::StringValue service_key(kKeyPrefixWifi + description.device_ssid); - - if (available) { - info.SetString(kDictionaryKeyServiceName, description.device_ssid); - info.SetString(kDictionaryKeyDisplayName, description.device_name); - info.SetString(kDictionaryKeyDescription, std::string()); - info.SetString(kDictionaryKeyType, description.device_kind); - info.SetBoolean(kDictionaryKeyIsWifi, true); - - web_ui()->CallJavascriptFunction( - "local_discovery.onUnregisteredDeviceUpdate", service_key, info); - } else { - scoped_ptr<base::Value> null_value(base::Value::CreateNullValue()); - - web_ui()->CallJavascriptFunction( - "local_discovery.onUnregisteredDeviceUpdate", service_key, *null_value); - } -} - -#endif // ENABLE_WIFI_BOOTSTRAPPING - } // namespace local_discovery
diff --git a/chrome/browser/ui/webui/local_discovery/local_discovery_ui_handler.h b/chrome/browser/ui/webui/local_discovery/local_discovery_ui_handler.h index dfa5559..fbe0d78 100644 --- a/chrome/browser/ui/webui/local_discovery/local_discovery_ui_handler.h +++ b/chrome/browser/ui/webui/local_discovery/local_discovery_ui_handler.h
@@ -9,13 +9,9 @@ #include <string> #include <vector> -#include "base/cancelable_callback.h" -#include "base/prefs/pref_member.h" -#include "chrome/browser/local_discovery/cloud_device_list.h" #include "chrome/browser/local_discovery/cloud_print_printer_list.h" #include "chrome/browser/local_discovery/privet_device_lister.h" #include "chrome/browser/local_discovery/privet_http.h" -#include "chrome/browser/local_discovery/privetv3_setup_flow.h" #include "components/signin/core/browser/signin_manager.h" #include "content/public/browser/web_ui_message_handler.h" @@ -23,11 +19,6 @@ #define CLOUD_PRINT_CONNECTOR_UI_AVAILABLE #endif -#if defined(ENABLE_WIFI_BOOTSTRAPPING) -#include "chrome/browser/local_discovery/wifi/bootstrapping_device_lister.h" -#include "chrome/browser/local_discovery/wifi/wifi_manager.h" -#endif - // TODO(noamsml): Factor out full registration flow into single class namespace local_discovery { @@ -42,7 +33,6 @@ // into the Javascript to update the page. class LocalDiscoveryUIHandler : public content::WebUIMessageHandler, public PrivetRegisterOperation::Delegate, - public PrivetV3SetupFlow::Delegate, public PrivetDeviceLister::Delegate, public CloudDeviceListDelegate, public SigninManagerBase::Observer { @@ -66,17 +56,6 @@ void OnPrivetRegisterDone(PrivetRegisterOperation* operation, const std::string& device_id) override; - // PrivetV3SetupFlow::Delegate implementation. - scoped_ptr<GCDApiFlow> CreateApiFlow() override; - void GetWiFiCredentials(const CredentialsCallback& callback) override; - void SwitchToSetupWiFi(const ResultCallback& callback) override; - void CreatePrivetV3Client(const std::string& service_name, - const PrivetClientCallback& callback) override; - void ConfirmSecurityCode(const ResultCallback& callback) override; - void RestoreWifi(const ResultCallback& callback) override; - void OnSetupDone() override; - void OnSetupError() override; - // PrivetDeviceLister::Delegate implementation. void DeviceChanged(bool added, const std::string& name, @@ -97,6 +76,7 @@ private: typedef std::map<std::string, DeviceDescription> DeviceDescriptionMap; + typedef base::Callback<void(bool result)> ResultCallback; // Message handlers: // For when the page is ready to receive device notifications. @@ -108,9 +88,6 @@ // For when a user choice is made. void HandleRegisterDevice(const base::ListValue* args); - // For when a code is confirmed. - void HandleConfirmCode(const base::ListValue* args); - // For when a cancellation is made. void HandleCancelRegistration(const base::ListValue* args); @@ -146,10 +123,8 @@ // Reset and cancel the current registration. void ResetCurrentRegistration(); - // Creates |PrivetV3HTTPClient| privet from |PrivetHTTPClient| and calls - // callback. - void PrivetClientToV3(const PrivetClientCallback& callback, - scoped_ptr<PrivetHTTPClient> client); + scoped_ptr<GCDApiFlow> CreateApiFlow(); + void OnSetupError(); // Announcement hasn't been sent for a certain time after registration // finished. Consider it failed. @@ -172,13 +147,6 @@ void RefreshCloudPrintStatusFromService(); #endif -#if defined(ENABLE_WIFI_BOOTSTRAPPING) - void StartWifiBootstrapping(); - void OnBootstrappingDeviceChanged( - bool available, - const wifi::BootstrappingDeviceDescription& description); -#endif - // A map of current device descriptions provided by the PrivetDeviceLister. DeviceDescriptionMap device_descriptions_; @@ -197,9 +165,6 @@ // The current register operation. Only one allowed at any time. scoped_ptr<PrivetRegisterOperation> current_register_operation_; - // The current Privet v3 setup operation. Only one allowed at any time. - scoped_ptr<PrivetV3SetupFlow> current_setup_operation_; - // The current confirm call used during the registration flow. scoped_ptr<GCDApiFlow> confirm_api_call_flow_; @@ -211,11 +176,9 @@ // List of printers from cloud print. scoped_ptr<GCDApiFlow> cloud_print_printer_list_; - scoped_ptr<GCDApiFlow> cloud_device_list_; std::vector<Device> cloud_devices_; int failed_list_count_; int succeded_list_count_; - ResultCallback device_code_callback_; #if defined(CLOUD_PRINT_CONNECTOR_UI_AVAILABLE) StringPrefMember cloud_print_connector_email_; @@ -223,11 +186,6 @@ bool cloud_print_connector_ui_enabled_; #endif -#if defined(ENABLE_WIFI_BOOTSTRAPPING) - scoped_ptr<wifi::WifiManager> wifi_manager_; - scoped_ptr<wifi::BootstrappingDeviceLister> bootstrapping_device_lister_; -#endif - DISALLOW_COPY_AND_ASSIGN(LocalDiscoveryUIHandler); };
diff --git a/chrome/browser/ui/webui/mojo_web_ui_controller.cc b/chrome/browser/ui/webui/mojo_web_ui_controller.cc index 286fcc1..65e40ae9 100644 --- a/chrome/browser/ui/webui/mojo_web_ui_controller.cc +++ b/chrome/browser/ui/webui/mojo_web_ui_controller.cc
@@ -9,7 +9,7 @@ #include "content/public/browser/render_process_host.h" #include "content/public/browser/web_ui_data_source.h" #include "content/public/common/bindings_policy.h" -#include "mojo/public/cpp/system/core.h" +#include "third_party/mojo/src/mojo/public/cpp/system/core.h" MojoWebUIControllerBase::MojoWebUIControllerBase(content::WebUI* contents) : WebUIController(contents), mojo_data_source_(NULL) {
diff --git a/chrome/browser/ui/webui/mojo_web_ui_controller.h b/chrome/browser/ui/webui/mojo_web_ui_controller.h index ed4b9e2..bb934df 100644 --- a/chrome/browser/ui/webui/mojo_web_ui_controller.h +++ b/chrome/browser/ui/webui/mojo_web_ui_controller.h
@@ -14,7 +14,7 @@ #include "content/public/browser/render_view_host.h" #include "content/public/browser/web_ui_controller.h" #include "content/public/common/service_registry.h" -#include "mojo/public/cpp/system/core.h" +#include "third_party/mojo/src/mojo/public/cpp/system/core.h" class MojoWebUIHandler;
diff --git a/chrome/browser/ui/webui/ntp/app_launcher_handler.cc b/chrome/browser/ui/webui/ntp/app_launcher_handler.cc index 5e243bf0..9f336ec5 100644 --- a/chrome/browser/ui/webui/ntp/app_launcher_handler.cc +++ b/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
@@ -565,8 +565,7 @@ base::AutoReset<bool> auto_reset(&ignore_changes_, true); extensions::SetLaunchType( - extension_service_, - extension_id, + Profile::FromWebUI(web_ui()), extension_id, static_cast<extensions::LaunchType>(static_cast<int>(launch_type))); }
diff --git a/chrome/browser/ui/webui/options/advanced_options_utils_linux.cc b/chrome/browser/ui/webui/options/advanced_options_utils_linux.cc index cda35a1f..6c7f5bbf 100644 --- a/chrome/browser/ui/webui/options/advanced_options_utils_linux.cc +++ b/chrome/browser/ui/webui/options/advanced_options_utils_linux.cc
@@ -97,7 +97,7 @@ LOG(ERROR) << "StartProxyConfigUtil failed to start " << command[0]; return false; } - base::EnsureProcessGetsReaped(process.pid()); + base::EnsureProcessGetsReaped(process.Pid()); return true; }
diff --git a/chrome/browser/ui/webui/options/chromeos/internet_options_handler.cc b/chrome/browser/ui/webui/options/chromeos/internet_options_handler.cc index 3ddda05..94a19eda 100644 --- a/chrome/browser/ui/webui/options/chromeos/internet_options_handler.cc +++ b/chrome/browser/ui/webui/options/chromeos/internet_options_handler.cc
@@ -576,7 +576,7 @@ // out a more robust way to track errors. Service.Error is transient so we // use NetworkState.error() which accurately tracks the "last" error. dictionary->SetString(kTagErrorMessage, - ui::NetworkConnect::Get()->GetErrorString( + ui::NetworkConnect::Get()->GetShillErrorString( network->error(), service_path)); // Add additional non-ONC cellular properties to inform the UI. if (network->type() == shill::kTypeCellular) {
diff --git a/chrome/browser/ui/webui/options/content_settings_handler.cc b/chrome/browser/ui/webui/options/content_settings_handler.cc index 929a618..64a3c3f 100644 --- a/chrome/browser/ui/webui/options/content_settings_handler.cc +++ b/chrome/browser/ui/webui/options/content_settings_handler.cc
@@ -244,13 +244,6 @@ } } -// Sort ZoomLevelChanges by host and scheme -// (a.com < http://a.com < https://a.com < b.com). -bool HostZoomSort(const content::HostZoomMap::ZoomLevelChange& a, - const content::HostZoomMap::ZoomLevelChange& b) { - return a.host == b.host ? a.scheme < b.scheme : a.host < b.host; -} - } // namespace namespace options { @@ -329,7 +322,7 @@ {"pluginsDetect", IDS_PLUGIN_DETECT_RADIO}, {"pluginsAsk", IDS_PLUGIN_ASK_RADIO}, {"pluginsBlock", IDS_PLUGIN_BLOCK_RADIO}, - {"disableIndividualPlugins", IDS_PLUGIN_SELECTIVE_DISABLE}, + {"manageIndividualPlugins", IDS_PLUGIN_MANAGE_INDIVIDUAL}, // Pop-ups filter. {"popupsTabLabel", IDS_POPUP_TAB_LABEL}, {"popups_header", IDS_POPUP_HEADER}, @@ -1040,7 +1033,13 @@ AdjustZoomLevelsListForSigninPageIfNecessary(&zoom_levels); - std::sort(zoom_levels.begin(), zoom_levels.end(), HostZoomSort); + // Sort ZoomLevelChanges by host and scheme + // (a.com < http://a.com < https://a.com < b.com). + std::sort(zoom_levels.begin(), zoom_levels.end(), + [](const content::HostZoomMap::ZoomLevelChange& a, + const content::HostZoomMap::ZoomLevelChange& b) { + return a.host == b.host ? a.scheme < b.scheme : a.host < b.host; + }); for (content::HostZoomMap::ZoomLevelVector::const_iterator i = zoom_levels.begin();
diff --git a/chrome/browser/ui/webui/theme_source.cc b/chrome/browser/ui/webui/theme_source.cc index bccb665..d7793ed 100644 --- a/chrome/browser/ui/webui/theme_source.cc +++ b/chrome/browser/ui/webui/theme_source.cc
@@ -40,6 +40,24 @@ static const char* kNewTabCSSPath = "css/new_tab_theme.css"; static const char* kNewIncognitoTabCSSPath = "css/incognito_new_tab_theme.css"; +void ProcessImageOnUIThread(const gfx::ImageSkia& image, + float scale_factor, + scoped_refptr<base::RefCountedBytes> data) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + const gfx::ImageSkiaRep& rep = image.GetRepresentation(scale_factor); + gfx::PNGCodec::EncodeBGRASkBitmap( + rep.sk_bitmap(), false /* discard transparency */, &data->data()); +} + +void ProcessResourceOnUIThread(int resource_id, + float scale_factor, + scoped_refptr<base::RefCountedBytes> data) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + ProcessImageOnUIThread( + *ResourceBundle::GetSharedInstance().GetImageSkiaNamed(resource_id), + scale_factor, data); +} + } // namespace //////////////////////////////////////////////////////////////////////////////// @@ -179,24 +197,23 @@ // rescale the bitmap if its backend doesn't contain the representation for // the specified scale factor. This is the fallback path in case chrome is // shipped without 2x resource pack but needs to use HighDPI display, which - // can happen in ChromeOS. - // TODO(mukai): remove this method itself when we ship 2x resource to all - // ChromeOS devices. - gfx::ImageSkia image; + // can happen in ChromeOS or Linux. + scoped_refptr<base::RefCountedBytes> data(new base::RefCountedBytes()); if (BrowserThemePack::IsPersistentImageID(resource_id)) { DCHECK_CURRENTLY_ON(BrowserThread::UI); ui::ThemeProvider* tp = ThemeServiceFactory::GetForProfile(profile_); DCHECK(tp); - image = *tp->GetImageSkiaNamed(resource_id); + ProcessImageOnUIThread(*tp->GetImageSkiaNamed(resource_id), scale_factor, + data); + callback.Run(data.get()); } else { DCHECK_CURRENTLY_ON(BrowserThread::IO); - image = *rb.GetImageSkiaNamed(resource_id); + // Fetching image data in ResourceBundle should happen on the UI thread. See + // crbug.com/449277 + content::BrowserThread::PostTaskAndReply( + content::BrowserThread::UI, FROM_HERE, + base::Bind(&ProcessResourceOnUIThread, resource_id, scale_factor, data), + base::Bind(callback, data)); } - - const gfx::ImageSkiaRep& rep = image.GetRepresentation(scale_factor); - scoped_refptr<base::RefCountedBytes> data(new base::RefCountedBytes()); - gfx::PNGCodec::EncodeBGRASkBitmap( - rep.sk_bitmap(), false /* discard transparency */, &data->data()); - callback.Run(data.get()); }
diff --git a/chrome/browser/web_dev_style/html_checker.py b/chrome/browser/web_dev_style/html_checker.py index 0addcd71..408ff909 100644 --- a/chrome/browser/web_dev_style/html_checker.py +++ b/chrome/browser/web_dev_style/html_checker.py
@@ -17,7 +17,7 @@ def LabelCheck(self, line_number, line): return regex_check.RegexCheck(self.input_api.re, line_number, line, - "(for=)", + r"(?:^|\s)(for=)", "Avoid 'for' attribute on <label>. Place the input within the <label>, " "or use aria-labelledby for <select>.")
diff --git a/chrome/chrome_android_paks.gypi b/chrome/chrome_android_paks.gypi index 574d5cc..13f5845 100644 --- a/chrome/chrome_android_paks.gypi +++ b/chrome/chrome_android_paks.gypi
@@ -121,5 +121,23 @@ }], ], }, + 'targets': [ + { + 'target_name': 'chrome_android_paks_copy', + 'type': 'none', + 'dependencies': [ + '<(DEPTH)/chrome/chrome_resources.gyp:packed_resources', + '<(DEPTH)/chrome/chrome_resources.gyp:packed_extra_resources', + ], + 'copies': [ + { + 'destination': '<(chrome_android_pak_output_folder)', + 'files': [ + '<@(chrome_android_pak_input_resources)', + ], + } + ], + }, + ], }
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 69c5fb83..18d4c524 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi
@@ -1490,8 +1490,6 @@ 'browser/history/chrome_history_client_factory.h', 'browser/history/delete_directive_handler.cc', 'browser/history/delete_directive_handler.h', - 'browser/history/expire_history_backend.cc', - 'browser/history/expire_history_backend.h', 'browser/history/history_backend.cc', 'browser/history/history_backend.h', 'browser/history/history_backend_android.cc', @@ -1762,6 +1760,8 @@ 'browser/net/safe_search_util.h', 'browser/net/service_providers_win.cc', 'browser/net/service_providers_win.h', + 'browser/net/spdyproxy/data_reduction_proxy_chrome_io_data.cc', + 'browser/net/spdyproxy/data_reduction_proxy_chrome_io_data.h', 'browser/net/spdyproxy/data_reduction_proxy_chrome_settings.cc', 'browser/net/spdyproxy/data_reduction_proxy_chrome_settings.h', 'browser/net/spdyproxy/data_reduction_proxy_chrome_settings_factory.cc', @@ -2317,10 +2317,6 @@ 'browser/safe_browsing/incident_reporting/module_integrity_verifier_win.h', 'browser/safe_browsing/incident_reporting/off_domain_inclusion_detector.cc', 'browser/safe_browsing/incident_reporting/off_domain_inclusion_detector.h', - 'browser/safe_browsing/incident_reporting/omnibox_interaction_incident.cc', - 'browser/safe_browsing/incident_reporting/omnibox_interaction_incident.h', - 'browser/safe_browsing/incident_reporting/omnibox_watcher.cc', - 'browser/safe_browsing/incident_reporting/omnibox_watcher.h', 'browser/safe_browsing/incident_reporting/preference_validation_delegate.cc', 'browser/safe_browsing/incident_reporting/preference_validation_delegate.h', 'browser/safe_browsing/incident_reporting/tracked_preference_incident.cc', @@ -2413,14 +2409,8 @@ 'browser/local_discovery/privet_notifications_factory.h', 'browser/local_discovery/privet_url_fetcher.cc', 'browser/local_discovery/privet_url_fetcher.h', - 'browser/local_discovery/privetv3_crypto_provider.cc', - 'browser/local_discovery/privetv3_crypto_provider.h', 'browser/local_discovery/privetv3_session.cc', 'browser/local_discovery/privetv3_session.h', - 'browser/local_discovery/privetv3_setup_flow.cc', - 'browser/local_discovery/privetv3_setup_flow.h', - 'browser/local_discovery/privetv3_setup_operation.cc', - 'browser/local_discovery/privetv3_setup_operation.h', 'browser/local_discovery/service_discovery_client_mac.h', 'browser/local_discovery/service_discovery_client_mac.mm', 'browser/local_discovery/service_discovery_client_mac_factory.h', @@ -2822,10 +2812,6 @@ 'browser/media/webrtc_rtp_dump_writer.h', ], 'chrome_browser_wifi_bootstrapping_sources': [ - 'browser/local_discovery/wifi/bootstrapping_device_lister.cc', - 'browser/local_discovery/wifi/bootstrapping_device_lister.h', - 'browser/local_discovery/wifi/bootstrapping_network_switcher.cc', - 'browser/local_discovery/wifi/bootstrapping_network_switcher.h', 'browser/local_discovery/wifi/credential_getter_win.cc', 'browser/local_discovery/wifi/credential_getter_win.h', 'browser/local_discovery/wifi/wifi_manager.cc',
diff --git a/chrome/chrome_browser_chromeos.gypi b/chrome/chrome_browser_chromeos.gypi index 9e1cad5..efcf2de6 100644 --- a/chrome/chrome_browser_chromeos.gypi +++ b/chrome/chrome_browser_chromeos.gypi
@@ -139,6 +139,7 @@ 'browser/chromeos/drive/file_system/touch_operation.h', 'browser/chromeos/drive/file_system/truncate_operation.cc', 'browser/chromeos/drive/file_system/truncate_operation.h', + 'browser/chromeos/drive/file_system_interface.cc', 'browser/chromeos/drive/file_system_interface.h', 'browser/chromeos/drive/file_system_metadata.cc', 'browser/chromeos/drive/file_system_metadata.h',
diff --git a/chrome/chrome_browser_extensions.gypi b/chrome/chrome_browser_extensions.gypi index 7373c5a..9c85311 100644 --- a/chrome/chrome_browser_extensions.gypi +++ b/chrome/chrome_browser_extensions.gypi
@@ -26,6 +26,8 @@ 'browser/extensions/api/messaging/native_message_host_chromeos.cc', 'browser/extensions/api/networking_private/crypto_verify_impl.cc', 'browser/extensions/api/networking_private/crypto_verify_impl.h', + 'browser/extensions/api/platform_keys/platform_keys_api.cc', + 'browser/extensions/api/platform_keys/platform_keys_api.h', 'browser/extensions/api/terminal/terminal_extension_helper.cc', 'browser/extensions/api/terminal/terminal_extension_helper.h', 'browser/extensions/api/terminal/terminal_private_api.cc',
diff --git a/chrome/chrome_browser_ui.gypi b/chrome/chrome_browser_ui.gypi index 7c16457..00703f1d 100644 --- a/chrome/chrome_browser_ui.gypi +++ b/chrome/chrome_browser_ui.gypi
@@ -1435,10 +1435,16 @@ 'browser/ui/exclusive_access/exclusive_access_bubble.h', 'browser/ui/exclusive_access/exclusive_access_bubble_type.cc', 'browser/ui/exclusive_access/exclusive_access_bubble_type.h', + 'browser/ui/exclusive_access/exclusive_access_controller_base.cc', + 'browser/ui/exclusive_access/exclusive_access_controller_base.h', + 'browser/ui/exclusive_access/exclusive_access_manager.cc', + 'browser/ui/exclusive_access/exclusive_access_manager.h', 'browser/ui/exclusive_access/fullscreen_controller.cc', 'browser/ui/exclusive_access/fullscreen_controller.h', 'browser/ui/exclusive_access/fullscreen_within_tab_helper.cc', 'browser/ui/exclusive_access/fullscreen_within_tab_helper.h', + 'browser/ui/exclusive_access/mouse_lock_controller.cc', + 'browser/ui/exclusive_access/mouse_lock_controller.h', 'browser/ui/fast_unload_controller.cc', 'browser/ui/fast_unload_controller.h', 'browser/ui/find_bar/find_bar_controller.cc',
diff --git a/chrome/chrome_renderer.gypi b/chrome/chrome_renderer.gypi index 9cb878a..675083f 100644 --- a/chrome/chrome_renderer.gypi +++ b/chrome/chrome_renderer.gypi
@@ -94,8 +94,6 @@ 'renderer/extensions/chrome_v8_context.h', 'renderer/extensions/chrome_v8_extension_handler.cc', 'renderer/extensions/chrome_v8_extension_handler.h', - 'renderer/extensions/enterprise_platform_keys_natives.cc', - 'renderer/extensions/enterprise_platform_keys_natives.h', 'renderer/extensions/extension_frame_helper.cc', 'renderer/extensions/extension_frame_helper.h', 'renderer/extensions/extension_localization_peer.cc', @@ -110,6 +108,8 @@ 'renderer/extensions/notifications_native_handler.h', 'renderer/extensions/page_capture_custom_bindings.cc', 'renderer/extensions/page_capture_custom_bindings.h', + 'renderer/extensions/platform_keys_natives.cc', + 'renderer/extensions/platform_keys_natives.h', 'renderer/extensions/renderer_permissions_policy_delegate.cc', 'renderer/extensions/renderer_permissions_policy_delegate.h', 'renderer/extensions/resource_request_policy.cc',
diff --git a/chrome/chrome_shell.gypi b/chrome/chrome_shell.gypi index 247ae5e..2de7f00 100644 --- a/chrome/chrome_shell.gypi +++ b/chrome/chrome_shell.gypi
@@ -95,7 +95,7 @@ 'type': 'none', 'dependencies': [ 'chrome_java', - 'chrome_shell_paks', + 'chrome_android_paks_copy', 'libchromeshell', '../media/media.gyp:media_java', ], @@ -129,22 +129,6 @@ 'includes': [ '../build/apk_fake_jar.gypi' ], }, { - 'target_name': 'chrome_shell_paks', - 'type': 'none', - 'dependencies': [ - '<(DEPTH)/chrome/chrome_resources.gyp:packed_resources', - '<(DEPTH)/chrome/chrome_resources.gyp:packed_extra_resources', - ], - 'copies': [ - { - 'destination': '<(chrome_android_pak_output_folder)', - 'files': [ - '<@(chrome_android_pak_input_resources)', - ], - } - ], - }, - { # GN: //chrome/android:chrome_sync_shell_manifest 'target_name': 'chrome_sync_shell_manifest', 'type': 'none', @@ -160,7 +144,7 @@ 'type': 'none', 'dependencies': [ 'chrome_java', - 'chrome_shell_paks', + 'chrome_android_paks_copy', 'libchromesyncshell', '../media/media.gyp:media_java', '../sync/sync.gyp:sync_java_test_support',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index 00f10a82..87e4cb3 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi
@@ -310,6 +310,7 @@ 'browser/media/chrome_webrtc_disable_encryption_flag_browsertest.cc', 'browser/media/chrome_webrtc_getmediadevices_browsertest.cc', 'browser/media/chrome_webrtc_perf_browsertest.cc', + 'browser/media/chrome_webrtc_simulcast_browsertest.cc', 'browser/media/chrome_webrtc_video_quality_browsertest.cc', 'browser/media/chrome_webrtc_webcam_browsertest.cc', 'browser/media/encrypted_media_istypesupported_browsertest.cc', @@ -386,6 +387,7 @@ 'browser/signin/easy_unlock_service_browsertest_chromeos.cc', 'browser/signin/signin_browsertest.cc', 'browser/spellchecker/spellcheck_service_browsertest.cc', + 'browser/ssl/captive_portal_blocking_page_browsertest.cc', 'browser/ssl/chrome_ssl_host_state_delegate_test.cc', 'browser/ssl/ssl_browser_tests.cc', 'browser/ssl/ssl_client_certificate_selector_test.cc', @@ -667,6 +669,7 @@ 'browser/chromeos/login/reset_browsertest.cc', # TODO(nkostylev) Re-enable ResourceLoaderBrowserTest. #'browser/chromeos/login/resource_loader_browsertest.cc', + 'browser/chromeos/login/proxy_auth_dialog_browsertest.cc', 'browser/chromeos/login/saml/saml_browsertest.cc', 'browser/chromeos/login/session_login_browsertest.cc', 'browser/chromeos/login/screens/mock_base_screen_delegate.cc', @@ -727,6 +730,7 @@ 'browser/chromeos/power/peripheral_battery_observer_browsertest.cc', 'browser/chromeos/preferences_browsertest.cc', 'browser/chromeos/profiles/profile_helper_browsertest.cc', + 'browser/chromeos/shutdown_policy_browsertest.cc', 'browser/chromeos/system/device_disabling_browsertest.cc', 'browser/chromeos/system/tray_accessibility_browsertest.cc', 'browser/ui/webui/options/chromeos/accounts_options_browsertest.cc', @@ -3172,17 +3176,6 @@ 'telemetry_gpu_test.isolate', ], }, - { - 'target_name': 'gpu_unittests_run', - 'type': 'none', - 'dependencies': [ - '../gpu/gpu.gyp:gpu_unittests', - 'gpu_tests_base', - ], - 'sources': [ - 'gpu_unittests.isolate', - ], - }, ], 'conditions': [ ['internal_gles2_conform_tests==1', {
diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi index 7e80b91..9dd35a3 100644 --- a/chrome/chrome_tests_unit.gypi +++ b/chrome/chrome_tests_unit.gypi
@@ -964,7 +964,6 @@ 'browser/local_discovery/privet_http_unittest.cc', 'browser/local_discovery/privet_url_fetcher_unittest.cc', 'browser/local_discovery/privetv3_session_unittest.cc', - 'browser/local_discovery/privetv3_setup_flow_unittest.cc', 'browser/local_discovery/service_discovery_client_mac_unittest.mm', ], 'chrome_unit_tests_configuration_policy_sources': [ @@ -1537,10 +1536,6 @@ 'browser/ui/app_list/test/fake_profile_store.h', 'browser/ui/app_list/test/fast_show_pickler_unittest.cc', ], - 'chrome_unit_tests_wifi_bootstrapping_sources': [ - 'browser/local_discovery/wifi/bootstrapping_device_lister_unittest.cc', - 'browser/local_discovery/wifi/bootstrapping_network_switcher_unittest.cc', - ], }, 'targets': [ { @@ -1561,7 +1556,6 @@ '../base/base.gyp:base_prefs_test_support', '../base/base.gyp:test_support_base', '../components/components.gyp:bookmarks_test_support', - '../components/components.gyp:component_updater_test_support', '../components/components.gyp:gcm_driver_test_support', '../components/components.gyp:history_core_test_support', '../components/components.gyp:invalidation', @@ -1575,6 +1569,7 @@ '../components/components.gyp:search_engines_test_support', '../components/components.gyp:signin_core_browser_test_support', '../components/components.gyp:sync_driver_test_support', + '../components/components.gyp:update_client_test_support', '../components/components.gyp:wallpaper', '../content/content.gyp:content_app_both', '../content/content_shell_and_tests.gyp:test_support_content', @@ -1650,6 +1645,8 @@ 'browser/search_engines/template_url_service_factory_test_util.h', 'browser/search_engines/template_url_service_test_util.cc', 'browser/search_engines/template_url_service_test_util.h', + 'browser/sessions/session_restore_test_helper.cc', + 'browser/sessions/session_restore_test_helper.h', 'browser/sessions/session_service_test_helper.cc', 'browser/sessions/session_service_test_helper.h', 'browser/signin/fake_account_reconcilor.cc', @@ -2599,9 +2596,6 @@ 'browser/plugins/plugin_installer_unittest.cc', ], }], - ['enable_wifi_bootstrapping', { - 'sources' : [ '<@(chrome_unit_tests_wifi_bootstrapping_sources)' ], - }], ], }, {
diff --git a/chrome/common/chrome_constants.cc b/chrome/common/chrome_constants.cc index aa08394..26ac251 100644 --- a/chrome/common/chrome_constants.cc +++ b/chrome/common/chrome_constants.cc
@@ -133,6 +133,7 @@ const char kInitialProfile[] = "Default"; const char kMultiProfileDirPrefix[] = "Profile "; const base::FilePath::CharType kGuestProfileDir[] = FPL("Guest Profile"); +const base::FilePath::CharType kSystemProfileDir[] = FPL("System Profile"); const wchar_t kBrowserResourcesDll[] = L"chrome.dll"; // filenames
diff --git a/chrome/common/chrome_constants.h b/chrome/common/chrome_constants.h index 09a8799..fa83106 100644 --- a/chrome/common/chrome_constants.h +++ b/chrome/common/chrome_constants.h
@@ -59,6 +59,7 @@ extern const char kInitialProfile[]; extern const char kMultiProfileDirPrefix[]; extern const base::FilePath::CharType kGuestProfileDir[]; +extern const base::FilePath::CharType kSystemProfileDir[]; extern const wchar_t kBrowserResourcesDll[]; // filenames
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc index 7cd9088..38d22de 100644 --- a/chrome/common/chrome_switches.cc +++ b/chrome/common/chrome_switches.cc
@@ -780,6 +780,12 @@ const char kManualEnhancedBookmarksOptout[] = "manual-enhanced-bookmarks-optout"; +// Use to opt-in to marking HTTP as non-secure. +const char kMarkNonSecureAs[] = "mark-non-secure-as"; +const char kMarkNonSecureAsNeutral[] = "neutral"; +const char kMarkNonSecureAsDubious[] = "dubious"; +const char kMarkNonSecureAsNonSecure[] = "non-secure"; + // Forces the maximum disk space to be used by the media cache, in bytes. const char kMediaCacheSize[] = "media-cache-size";
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h index a218d4e..c168e36 100644 --- a/chrome/common/chrome_switches.h +++ b/chrome/common/chrome_switches.h
@@ -219,6 +219,10 @@ extern const char kMakeDefaultBrowser[]; extern const char kManualEnhancedBookmarks[]; extern const char kManualEnhancedBookmarksOptout[]; +extern const char kMarkNonSecureAs[]; +extern const char kMarkNonSecureAsNeutral[]; +extern const char kMarkNonSecureAsDubious[]; +extern const char kMarkNonSecureAsNonSecure[]; extern const char kMediaCacheSize[]; extern const char kMessageLoopHistogrammer[]; extern const char kMetricsRecordingOnly[];
diff --git a/chrome/common/crash_keys.cc b/chrome/common/crash_keys.cc index 4356e629..858d9cc3 100644 --- a/chrome/common/crash_keys.cc +++ b/chrome/common/crash_keys.cc
@@ -264,7 +264,6 @@ flag == "--flag-switches-end"; #elif defined(OS_CHROMEOS) static const char* const kIgnoreSwitches[] = { - ::switches::kEnableImplSidePainting, ::switches::kEnableLogging, ::switches::kFlagSwitchesBegin, ::switches::kFlagSwitchesEnd,
diff --git a/chrome/common/extensions/api/_api_features.json b/chrome/common/extensions/api/_api_features.json index bee6ab4..26abbd0 100644 --- a/chrome/common/extensions/api/_api_features.json +++ b/chrome/common/extensions/api/_api_features.json
@@ -558,6 +558,11 @@ "extension_types": ["extension", "legacy_packaged_app", "platform_app"], "contexts": ["blessed_extension"] }, + "platformKeysInternal": [{ + "dependencies": ["permission:enterprise.platformKeys"], + "internal": true, + "contexts": ["blessed_extension"] + }], "preferencesPrivate": { "dependencies": ["permission:preferencesPrivate"], "contexts": ["blessed_extension"]
diff --git a/chrome/common/extensions/api/content_settings.json b/chrome/common/extensions/api/content_settings.json index 9ecc2d7..143b0a5 100644 --- a/chrome/common/extensions/api/content_settings.json +++ b/chrome/common/extensions/api/content_settings.json
@@ -228,6 +228,14 @@ "notifications", {"type":"string", "enum": ["allow", "block", "ask"]} ] + }, + "mouselock": { + "$ref": "ContentSetting", + "description": "Whether to allow sites to disable the mouse cursor. One of <br><var>allow</var>: Allow sites to disable the mouse cursor,<br><var>block</var>: Don't allow sites to disable the mouse cursor,<br><var>ask</var>: Ask when a site wants to disable the mouse cursor. <br>Default is <var>ask</var>.<br>The primary URL is the main-frame URL. The secondary URL is not used.", + "value": [ + "mouselock", + {"type":"string", "enum": ["allow", "block", "ask"]} + ] } } }
diff --git a/chrome/common/extensions/api/enterprise_platform_keys_internal.idl b/chrome/common/extensions/api/enterprise_platform_keys_internal.idl index 347f1a9..7d35f90f 100644 --- a/chrome/common/extensions/api/enterprise_platform_keys_internal.idl +++ b/chrome/common/extensions/api/enterprise_platform_keys_internal.idl
@@ -33,24 +33,5 @@ static void generateKey(DOMString tokenId, long modulusLength, GenerateKeyCallback callback); - - // Internal version of Token.sign. - // |tokenId| The id of a Token returned by |getTokens|. - // |publicKey| The Subject Public Key Info of a key previously generated by - // |generateKey| in DER encoding. - // |hashAlgorithmName| The recognized algorithm name as specified by - // WebCrypto of the hash algorithm that will be used to digest |data| - // before signing. Currently supported are: SHA-{1,256,384,512}. - // TODO(pneubeck): use an enum once supported: - // http://www.crbug.com/385539 . - // |data| The data to sign. - // |callback| Called back with the signature of |data|. - // TODO: Instead of ArrayBuffer should be (ArrayBuffer or ArrayBufferView), - // or at least (ArrayBuffer or Uint8Array). - static void sign(DOMString tokenId, - ArrayBuffer publicKey, - DOMString hashAlgorithmName, - ArrayBuffer data, - SignCallback callback); }; };
diff --git a/chrome/common/extensions/api/hotword_private.idl b/chrome/common/extensions/api/hotword_private.idl index 053c43cc..139ddab 100644 --- a/chrome/common/extensions/api/hotword_private.idl +++ b/chrome/common/extensions/api/hotword_private.idl
@@ -161,5 +161,8 @@ // Fired when a hotword has triggered. static void onHotwordTriggered(); + + // Fired when the speaker model should be deleted. + static void onDeleteSpeakerModel(); }; };
diff --git a/chrome/common/extensions/api/platform_keys_internal.idl b/chrome/common/extensions/api/platform_keys_internal.idl new file mode 100644 index 0000000..afd68e51 --- /dev/null +++ b/chrome/common/extensions/api/platform_keys_internal.idl
@@ -0,0 +1,34 @@ +// Copyright 2015 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. + +// Internal API for to implement the platformKeys and enterprise.platformKeys +// APIs. +[ implemented_in = "chrome/browser/extensions/api/platform_keys/platform_keys_api.h" ] +namespace platformKeysInternal { + // Invoked by <code>sign</code>. + // |signature| The signature, a octet string. + callback SignCallback = void(ArrayBuffer signature); + + interface Functions { + // Internal version of platformKeys.subtleCrypto.sign and + // enterprise.platformKeys.Token.subtleCrypto.sign. + // |tokenId| The id of a Token returned by |getTokens|. + // |publicKey| The Subject Public Key Info of a key previously generated by + // |generateKey| in DER encoding. + // |hashAlgorithmName| The recognized algorithm name as specified by + // WebCrypto of the hash algorithm that will be used to digest |data| + // before signing. Currently supported are: SHA-{1,256,384,512}. + // TODO(pneubeck): use an enum once supported: + // http://www.crbug.com/385539 . + // |data| The data to sign. + // |callback| Called back with the signature of |data|. + // TODO: Instead of ArrayBuffer should be (ArrayBuffer or ArrayBufferView), + // or at least (ArrayBuffer or Uint8Array). + static void sign(DOMString tokenId, + ArrayBuffer publicKey, + DOMString hashAlgorithmName, + ArrayBuffer data, + SignCallback callback); + }; +};
diff --git a/chrome/common/extensions/api/schemas.gypi b/chrome/common/extensions/api/schemas.gypi index 4d1c3565..17fd692d 100644 --- a/chrome/common/extensions/api/schemas.gypi +++ b/chrome/common/extensions/api/schemas.gypi
@@ -117,6 +117,7 @@ 'file_system_provider_internal.idl', 'first_run_private.json', 'log_private.idl', + 'platform_keys_internal.idl', 'wallpaper.json', 'wallpaper_private.json', ],
diff --git a/chrome/common/extensions/docs/static/css/out/site.css b/chrome/common/extensions/docs/static/css/out/site.css index dabe337..a5714c6 100644 --- a/chrome/common/extensions/docs/static/css/out/site.css +++ b/chrome/common/extensions/docs/static/css/out/site.css
@@ -1,4 +1,4 @@ /*! 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. - */article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none;height:0}[hidden],template{display:none}html{font-family:sans-serif;font-size:100%;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}button,input,select,textarea{font-family:sans-serif}body{margin:0}a{background:transparent}a:focus{outline:thin dotted}a:active,a:hover{outline:0}p,pre{margin:1.5em 0}blockquote{margin:1.5em 40px}h1{font-size:2em;line-height:1.5em;margin-top:0.75em;margin-bottom:0.75em}h2{font-size:1.5em;line-height:2em;margin-top:1em;margin-bottom:1em}h3{font-size:1.17em;line-height:1.28205em;margin-top:1.28205em;margin-bottom:1.28205em}h4{font-size:1em;line-height:1.5em;margin-top:1.5em;margin-bottom:1.5em}h5{font-size:0.83em;line-height:1.80723em;margin-top:1.80723em;margin-bottom:1.80723em}h6{font-size:0.67em;line-height:2.23881em;margin-top:2.23881em;margin-bottom:2.23881em}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}hr{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;height:0}mark{background:#ff0;color:#000}code,kbd,pre,samp{font-family:monospace, serif;_font-family:'courier new', monospace;font-size:1em}pre{white-space:pre;white-space:pre-wrap;word-wrap:break-word}q{quotes:"\201C" "\201D" "\2018" "\2019"}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}dl,menu,ol,ul{margin:1.5em 0}dd{margin:0 0 0 40px}menu,ol,ul{padding:0 0 0 40px}nav ul,nav ol{list-style:none;list-style-image:none}img{border:0;-ms-interpolation-mode:bicubic}svg:not(:root){overflow:hidden}figure{margin:0}form{margin:0}fieldset{margin:0 2px;border-color:#c0c0c0;border-top-style:solid;border-top-width:0.0625em;padding-top:0.4625em;border-bottom-style:solid;border-bottom-width:0.0625em;padding-bottom:0.9125em;border-left-style:solid;border-left-width:0.0625em;padding-left:0.875em;border-right-style:solid;border-right-width:0.0625em;padding-right:0.875em}legend{border:0;padding:0;*margin-left:-7px}button,input,select,textarea{font-family:inherit;font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}button,input{line-height:normal}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer;*overflow:visible}button[disabled],html input[disabled]{cursor:default}input[type="checkbox"],input[type="radio"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0;*height:13px;*width:13px}input[type="search"]{-webkit-appearance:textfield;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}textarea{overflow:auto;vertical-align:top}table{border-collapse:collapse;border-spacing:0}* html{font-size:100%}html{font-size:16px;line-height:1.5em}* html{font-size:100%}html{font-size:16px;line-height:1.5em}.g-section:after{content:".";display:block;height:0;clear:both;visibility:hidden}.g-unit .g-section:after{clear:none}.g-unit .g-section{width:100%;overflow:hidden}.g-section,.g-unit{zoom:1}.g-split>.g-unit{float:right;text-align:right}.g-split>.g-first{float:left;text-align:left}.g-tpl-160 .g-unit,.g-unit .g-tpl-160 .g-unit,.g-unit .g-unit .g-tpl-160 .g-unit,.g-unit .g-unit .g-unit .g-tpl-160 .g-unit,.g-unit .g-unit .g-unit .g-unit .g-tpl-160 .g-unit,.g-unit .g-unit .g-unit .g-unit .g-unit .g-tpl-160 .g-unit{display:block;margin:0 0 0 160px;width:auto;float:none}.g-tpl-160 .g-first,.g-unit .g-tpl-160 .g-first,.g-unit .g-unit .g-tpl-160 .g-first,.g-unit .g-unit .g-unit .g-tpl-160 .g-first,.g-unit .g-unit .g-unit .g-unit .g-tpl-160 .g-first,.g-unit .g-unit .g-unit .g-unit .g-unit .g-tpl-160 .g-first{display:block;margin:0;width:160px;float:left}.g-tpl-25-75 .g-unit,.g-unit .g-tpl-25-75 .g-unit,.g-unit .g-unit .g-tpl-25-75 .g-unit,.g-unit .g-unit .g-unit .g-tpl-25-75 .g-unit,.g-unit .g-unit .g-unit .g-unit .g-tpl-25-75 .g-unit,.g-unit .g-unit .g-unit .g-unit .g-unit .g-tpl-25-75 .g-unit{width:74.999%;float:right;display:inline;margin:0}.g-tpl-25-75 .g-first,.g-unit .g-tpl-25-75 .g-first,.g-unit .g-unit .g-tpl-25-75 .g-first,.g-unit .g-unit .g-unit .g-tpl-25-75 .g-first,.g-unit .g-unit .g-unit .g-unit .g-tpl-25-75 .g-first,.g-unit .g-unit .g-unit .g-unit .g-unit .g-tpl-25-75 .g-first{width:24.999%;float:left;display:inline;margin:0}.g-tpl-75-25 .g-unit,.g-unit .g-tpl-75-25 .g-unit,.g-unit .g-unit .g-tpl-75-25 .g-unit,.g-unit .g-unit .g-unit .g-tpl-75-25 .g-unit,.g-unit .g-unit .g-unit .g-unit .g-tpl-75-25 .g-unit,.g-unit .g-unit .g-unit .g-unit .g-unit .g-tpl-75-25 .g-unit{width:24.999%;float:right;display:inline;margin:0}.g-tpl-75-25 .g-first,.g-unit .g-tpl-75-25 .g-first,.g-unit .g-unit .g-tpl-75-25 .g-first,.g-unit .g-unit .g-unit .g-tpl-75-25 .g-first,.g-unit .g-unit .g-unit .g-unit .g-tpl-75-25 .g-first,.g-unit .g-unit .g-unit .g-unit .g-unit .g-tpl-75-25 .g-first{width:74.999%;float:left;display:inline;margin:0}.g-tpl-33-67 .g-unit,.g-unit .g-tpl-33-67 .g-unit,.g-unit .g-unit .g-tpl-33-67 .g-unit,.g-unit .g-unit .g-unit .g-tpl-33-67 .g-unit,.g-unit .g-unit .g-unit .g-unit .g-tpl-33-67 .g-unit,.g-unit .g-unit .g-unit .g-unit .g-unit .g-tpl-33-67 .g-unit{width:66.999%;float:right;display:inline;margin:0}.g-tpl-33-67 .g-first,.g-unit .g-tpl-33-67 .g-first,.g-unit .g-unit .g-tpl-33-67 .g-first,.g-unit .g-unit .g-unit .g-tpl-33-67 .g-first,.g-unit .g-unit .g-unit .g-unit .g-tpl-33-67 .g-first,.g-unit .g-unit .g-unit .g-unit .g-unit .g-tpl-33-67 .g-first{width:32.999%;float:left;display:inline;margin:0}.g-tpl-67-33 .g-unit,.g-unit .g-tpl-67-33 .g-unit,.g-unit .g-unit .g-tpl-67-33 .g-unit,.g-unit .g-unit .g-unit .g-tpl-67-33 .g-unit,.g-unit .g-unit .g-unit .g-unit .g-tpl-67-33 .g-unit,.g-unit .g-unit .g-unit .g-unit .g-unit .g-tpl-67-33 .g-unit{width:32.999%;float:right;display:inline;margin:0}.g-tpl-67-33 .g-first,.g-unit .g-tpl-67-33 .g-first,.g-unit .g-unit .g-tpl-67-33 .g-first,.g-unit .g-unit .g-unit .g-tpl-67-33 .g-first,.g-unit .g-unit .g-unit .g-unit .g-tpl-67-33 .g-first,.g-unit .g-unit .g-unit .g-unit .g-unit .g-tpl-67-33 .g-first{width:66.999%;float:left;display:inline;margin:0}.g-tpl-50-50 .g-unit,.g-unit .g-tpl-50-50 .g-unit,.g-unit .g-unit .g-tpl-50-50 .g-unit,.g-unit .g-unit .g-unit .g-tpl-50-50 .g-unit,.g-unit .g-unit .g-unit .g-unit .g-tpl-50-50 .g-unit,.g-unit .g-unit .g-unit .g-unit .g-unit .g-tpl-50-50 .g-unit{width:49.999%;float:right;display:inline;margin:0}.g-tpl-50-50 .g-first,.g-unit .g-tpl-50-50 .g-first,.g-unit .g-unit .g-tpl-50-50 .g-first,.g-unit .g-unit .g-unit .g-tpl-50-50 .g-first,.g-unit .g-unit .g-unit .g-unit .g-tpl-50-50 .g-first,.g-unit .g-unit .g-unit .g-unit .g-unit .g-tpl-50-50 .g-first{width:49.999%;float:left;display:inline;margin:0}.g-tpl-nest .g-unit{float:left;width:auto;display:inline;margin:0}.g-tpl-nest-alt .g-unit{float:right;width:auto;display:inline;margin:0}.g-content{margin-right:30px}.g-last .g-content{margin-right:0}@media only screen and (max-width: 580px){.g-unit.g-unit{float:none !important}.g-content{margin-right:0}}*{padding:0;margin:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html,body{overflow-x:hidden;overflow-y:auto}img{max-width:100%}#gc-container{max-width:870px;margin:auto;width:90%}#gc-pagecontent>.g-section{margin:40px 0}main{margin-bottom:50px;position:relative}footer[role="contentinfo"]{padding:40px 0 50px}@media only screen and (max-width: 580px){#gc-container{width:auto}#gc-pagecontent{margin:auto;width:90%}#gc-pagecontent>.g-section{margin:20px 0}footer[role="contentinfo"]{padding:20px 30px}}@media only screen and (min-width: 581px) and (max-width: 990px){#gc-container{width:95%}}figure{margin:20px 0}figure img{border:1px solid #dbdbdb}table{width:100%;border-collapse:collapse;margin:2em 0;line-height:1.5em}table caption{margin-bottom:1em;text-align:left;font-weight:bold}th{border:1px solid #dbdbdb;font-weight:bold;background:#e8e8e8}tr{border-bottom:1px solid #dbdbdb}table+tr{border-top:1px solid #dbdbdb}td,th{padding:1em 1.5em;text-align:left;border:1px solid #dbdbdb}pre{background-color:#f7f7f7;box-shadow:0 2px 4px rgba(0,0,0,0.15),0 0 3px rgba(0,0,0,0.15);margin:1em 0 0 0;padding:.99em;position:relative;overflow-x:auto;word-wrap:normal;white-space:pre;font-size:0.95em;line-height:1.8em}pre a{text-decoration:underline !important}pre b{background:yellow;font-weight:normal}pre strike{text-decoration:none;background-image:linear-gradient(transparent 7px,#cc1f1f 7px,#cc1f1f 9px,transparent 9px)}pre[data-filename]::after{visibility:hidden}pre[data-filename]:hover::after{visibility:visible}.element-invisible{position:absolute !important;height:1px;width:1px;overflow:hidden;clip:rect(1px 1px 1px 1px);clip:rect(1px, 1px, 1px, 1px)}.hidden{display:none}.label{color:inherit;text-transform:uppercase;margin-bottom:5px;font-size:11.2px;font-weight:bold}.published{font-size:11.2px;font-style:italic;color:#bebebe;line-height:16.8px}.description{margin:20px 0}.description:last-child{margin-bottom:0}.span-full{background:#f5f5f5;position:relative;padding:3em 0}.span-full::before,.span-full::after{content:'';height:100%;width:100%;top:0;position:absolute;background:#f5f5f5;z-index:-1}.span-full::before{left:-100%}.span-full::after{left:100%}.button{background:#0370ea;background-image:linear-gradient(top, #008dfd 0%,#0370ea 100%);border:1px solid #076bd2;border-radius:3px;color:#fff !important;display:inline-block;font-size:13px;font-weight:700;line-height:1.3;padding:5px 20px;text-align:center;text-decoration:none !important;text-shadow:1px 1px 1px #076bd2}.button:hover{background-image:linear-gradient(top, #008dfd 30%,#0370ea 100%);cursor:pointer}.button a{color:inherit !important}.button-alt{background:#eee;background-image:linear-gradient(bottom, #dcdcdc 46%,#fafafa 87%);border:1px solid #d6d6d6;border-radius:3px;color:#333 !important;display:inline-block;font-size:12px;font-weight:700;line-height:24px;padding:0 15px;text-align:center;text-decoration:none !important;text-shadow:none}.button-alt:hover{background-image:linear-gradient(bottom, #dcdcdc 20%,#fafafa 87%);cursor:pointer}.google-button{background-color:#f5f5f5;border-radius:2px 0 0 0;border:1px solid rgba(0,0,0,0.1);padding:5px 12px;text-align:center;white-space:nowrap}.google-button:hover{border-color:#c6c6c6;box-shadow:0 -1px 1px rgba(0,0,0,0.1)}.google-button:active{background-color:#f1f1f1;box-shadow:inset 0 0px 2px rgba(0,0,0,0.2)}.screenshot,.screenshot img{margin:1em 0}.video-container{position:relative;padding-bottom:56.25%;padding-top:30px;height:0;overflow:hidden;margin:0 0 20px 0}.video-container iframe,.video-container object,.video-container embed{position:absolute;top:0;left:0;width:100%;height:100%}p.note,p.caution,p.warning,div.note,div.caution,div.warning,aside.note,aside.caution,aside.warning{background-color:#f5f5f5;border-bottom:1px solid;border-top:1px solid;overflow:hidden;width:85%;padding:1em}p.note,div.note,aside.note{border-color:#36C}p.caution,div.caution,aside.caution{border-color:#FC3}p.warning,div.warning,aside.warning{border-color:#A03}p.warning em,p.warning strong,div.warning em,div.warning strong,aside.warning em,aside.warning strong{color:#A03}.permalink{display:none;margin-left:5px}.has-permalink:hover .permalink{display:initial}.no-permalink .permalink{display:none !important}#gc-footer .links a{margin-right:20px}#gc-footer #cc-info{font-size:11.2px}#social-buttons{display:-webkit-box;display:-webkit-flex;display:-moz-flex;display:-ms-flex;display:-o-flex;display:flex;-webkit-box-pack:1;-webkit-justify-content:flex-end;-moz-justify-content:flex-end;-ms-justify-content:flex-end;-o-justify-content:flex-end;justify-content:flex-end;-webkit-box-align:center;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-o-align-items:center;align-items:center}#social-buttons>*{margin-left:10px}#social-buttons img{margin:-4px 0 0 1px}@media only screen and (max-width: 580px){.more-section .g-last .g-content{padding-bottom:0;border:none}.more-section .g-content{border:1px solid #dbdbdb;border-width:0 0 1px 0;padding-bottom:20px;margin-bottom:20px}#gc-footer .links a{display:inline-block}}#scroll-to-top,#send-feedback{border-bottom:none;bottom:0;position:fixed;z-index:5}#scroll-to-top{border-left:0;left:0}#send-feedback{border-right:0;right:0}html{font-family:"Open Sans",Arial,"Lucida Grande",sans-serif;color:#777}body{font-size:13px;color:#777}h1,h2,h3,h4,h5,h6{font-family:"Open Sans",Arial,"Lucida Grande",sans-serif;font-weight:600;color:#000}h1,h2{font-weight:300}h1{font-size:2.625em;line-height:1.14286em}h1+h1{margin-top:0em}h2{font-size:1.875em;line-height:1.6em;margin-top:1.6em;margin-bottom:0em;line-height:1.12em}h3{font-size:1.125em;line-height:1.33333em;margin-top:1.33333em;margin-bottom:0.53333em;line-height:1.12em}h4{font-size:1.1em;line-height:1.36364em;margin-top:0em;margin-bottom:0em}h5{font-size:1em;line-height:1.5em;margin-top:0em;margin-bottom:0em}h6{font-size:1em;line-height:1.5em;margin-top:0em;margin-bottom:0em}p{margin:1.5em 0}p.noindent,p.caption p{text-indent:0}p.caption{text-align:left;margin-top:9px;font-weight:bold}.lightbox p.caption{color:#fff}a,a:link,a:visited{color:#39c;font-weight:bold;text-decoration:none;word-wrap:break-word;transition:opacity 0.3s ease 0s}a:hover,a:focus,a:link:hover,a:link:focus,a:visited:hover,a:visited:focus{color:#39f}a.section-anchor{display:block;padding-top:3.33em}footer[role="contentinfo"]{font-size:0.84615385em}footer[role="contentinfo"] a,footer[role="contentinfo"] a:link,footer[role="contentinfo"] a:visited{color:#999;font-weight:normal;font-weight:600;text-decoration:none;word-wrap:break-word}footer[role="contentinfo"] a:hover,footer[role="contentinfo"] a:focus,footer[role="contentinfo"] a:link:hover,footer[role="contentinfo"] a:link:focus,footer[role="contentinfo"] a:visited:hover,footer[role="contentinfo"] a:visited:focus{color:#39f}table{font-size:13px}td dl{margin:0.4em 0}td dt{margin:0 0 0.4em 0}em{padding-right:2px}img{vertical-align:middle}figcaption{font-family:"Open Sans",Arial,"Lucida Grande",sans-serif;color:#aaa}blockquote{margin:0.75em 0.8em}cite{margin:0.75em 0.8em;color:#c3c3c3;font-style:normal}canvas{background:#fff;margin:1.5em 0}.code,code,pre{color:#080;font-family:"Source Code Pro",sans-serif}a>code{color:#39c}pre{margin:2em 0;word-wrap:break-word;position:relative}pre[data-filename]::after{content:attr(data-filename);background-color:#aaa;color:#fff;padding:2px 12px;position:absolute;right:0;top:0}pre a{text-decoration:underline}.static-code-container{line-height:1em;clear:both}code,kbd,samp{margin:1.5em 0;line-height:1em}dl,menu,ol,ul,.item-list ul{margin:0.8em 0}ul{padding-left:1.28em}ol{padding-left:1.52em}hr{height:1px;border:0;border-bottom:1px solid #dbdbdb;padding-bottom:-1px;margin:1.5em 0}[data-list-item]{display:list-item}.kbd{background-color:#f7f7f7;border:1px solid #ccc;color:#333;font-size:11px;line-height:1.4;text-shadow:0 1px 0 #fff;font-family:Arial,Helvetica,sans-serif;display:inline-block;padding:0.1em 0.6em;margin:0 0.1em;white-space:nowrap;box-shadow:0 1px 0px rgba(0,0,0,0.2),0 0 0 2px #fff inset;border-radius:3px}#topnav{display:-webkit-box;display:-webkit-flex;display:-moz-flex;display:-ms-flex;display:-o-flex;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-o-align-items:center;align-items:center;height:64px;position:relative}#logo{display:-webkit-box;display:-webkit-flex;display:-moz-flex;display:-ms-flex;display:-o-flex;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-o-align-items:center;align-items:center;-webkit-user-select:none;-moz-user-select:none;-o-user-select:none;-ms-user-select:none;user-select:none}#logo a{display:-webkit-box;display:-webkit-flex;display:-moz-flex;display:-ms-flex;display:-o-flex;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-o-align-items:center;align-items:center;color:#828282;font-size:2em;font-weight:400;letter-spacing:-1px}#logo a img{margin-bottom:-4px;height:40px;width:123px}#logo .collase-icon{display:none;background:url("../../images/burger-icon.png") 50% 100% no-repeat;background-size:cover;width:20px;height:20px}#logo .collase-icon.active{background-position:50% 0}#fatnav{height:100%;display:-webkit-box;display:-webkit-flex;display:-moz-flex;display:-ms-flex;display:-o-flex;display:flex;-webkit-box-pack:1;-webkit-justify-content:flex-end;-moz-justify-content:flex-end;-ms-justify-content:flex-end;-o-justify-content:flex-end;justify-content:flex-end;-webkit-box-flex:1;-webkit-flex:1;-moz-flex:1;-ms-flex:1;-o-flex:1;flex:1;white-space:nowrap}#fatnav li{list-style:none}#fatnav>ul{display:-webkit-box;display:-webkit-flex;display:-moz-flex;display:-ms-flex;display:-o-flex;display:flex;padding:0;margin:0}#fatnav .toplevel{color:#aaa;font-weight:600;text-transform:uppercase;-webkit-user-select:none;-moz-user-select:none;-o-user-select:none;-ms-user-select:none;user-select:none}#fatnav .toplevel::after{content:'';background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAPJJREFUeNpiyc/Pn8XAwDATiM8yEAaMQBwBxHxMQMIdiE8D8Vog1sGjyQGqbhkQK4A0PoKaFATEF4F4MRCrImnQBuJtQLwfiI2hYk9AGl2AuB2I/wAxiB8DxNeAeA4QzwXiS0DsCdXwHIj9gHgqSOFPIK4CYksgvgJVwALEyUCcBDWMAeoSkO2bGZAEQeAM1CmtUNth4BkQ+wJxHBC/hwkyoQXALyCuAWILIL4MxIugAbYFI3iNZ54BR4fNtcXo0QEy9B+ywBGtWMzoAAquBWLk6EDXhBIdLNDokINGRwBQAUiiCYhvI0VHN1LIjpjoAAgwAMoSTlKlzAY4AAAAAElFTkSuQmCC) no-repeat;background-size:9px;display:inline-block;height:5px;width:14px;margin-left:10px;margin-bottom:2px}#fatnav .pillar{display:-webkit-box;display:-webkit-flex;display:-moz-flex;display:-ms-flex;display:-o-flex;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-o-align-items:center;align-items:center;padding:0 20px;cursor:pointer;z-index:1002}#fatnav .expandee{display:none;position:absolute;z-index:1001;left:0;width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;background-color:#f5f5f5;padding:20px 0;cursor:initial;margin:0}#fatnav .expandee a{font-weight:600;padding:0.5em 0;display:block;color:#828282}#fatnav .expandee a:hover{background-image:linear-gradient(205deg, rgba(229,229,229,0.7) 0%,rgba(233,233,233,0.7) 20%,rgba(244,244,244,0.7) 100%)}#fatnav .expandee a.highlight{color:#000;background-image:linear-gradient(205deg, rgba(229,229,229,0.7) 0%,rgba(233,233,233,0.7) 20%,rgba(244,244,244,0.7) 100%)}#fatnav .expandee li{white-space:nowrap}#fatnav .expandee li.submenu{color:#333;font-size:1.1em;font-weight:bold;-webkit-box-flex:1;-webkit-flex:1;-moz-flex:1;-ms-flex:1;-o-flex:1;flex:1}#fatnav .expandee li.submenu.active{background-image:linear-gradient(205deg, rgba(229,229,229,0.7) 0%,rgba(233,233,233,0.7) 20%,rgba(244,244,244,0.7) 100%)}#fatnav .expandee li.submenu>ul{font-size:0.8em;padding:15px 0 0 0;margin:0}#fatnav .expandee li.submenu .category{border-bottom:1px solid #e8e8e8}#fatnav .expandee li.submenu .category:last-child{border:none}#fatnav .expandee li.submenu .category a{overflow:hidden;text-overflow:ellipsis}#fatnav .expandee li.submenu .category>ul{display:none}#fatnav .expandee li.submenu .category ul{padding:0}#search{display:-webkit-inline-flex;display:-moz-inline-flex;display:-ms-inline-flex;display:-o-inline-flex;display:inline-flex;-webkit-align-self:stretch;-moz-align-self:stretch;-ms-align-self:stretch;-o-align-self:stretch;align-self:stretch;-webkit-box-align:center;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-o-align-items:center;align-items:center;width:auto;padding:0 20px;cursor:pointer}#search img{height:16px;width:16px;-webkit-user-select:none;-moz-user-select:none;-o-user-select:none;-ms-user-select:none;user-select:none}#search .expandee{padding:20px}#search .expandee input[type="search"]{width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;background:url("../../images/search.png") no-repeat 15px 55%;background-size:20px;background-color:white;border:1px solid #dbdbdb;padding:10px 10px 10px 40px;font-size:1.4em;-webkit-box-flex:1;-webkit-flex:1;-moz-flex:1;-ms-flex:1;-o-flex:1;flex:1;font-family:inherit;font-weight:300}@media only screen and (min-width: 580px){#topnav{padding:15px 0 0}#fatnav .pillar.highlight .toplevel{color:#000}#fatnav .pillar.active{background:#f5f5f5 url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAyCAMAAABI+VrBAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAALFQTFRF/////f39/v7+/Pz8+/v7+fn56+vr+vr69PT09vb28/Pz9fX1xcXF9/f3+Pj45+fn8PDwycnJ7+/v6enpzc3N19fX8fHx8vLy7u7u6Ojo7Ozs3Nzc5OTk7e3t4uLi2dnZ39/fxsbG29vb0dHR3d3d4ODg4+Pj6urqyMjI09PT5eXl0NDQ1dXV2NjYysrKx8fH5ubmzs7O3t7exMTE4eHh2tray8vLz8/PzMzM1NTU1tbWhgtdWwAAAOFJREFUeNok0NWSxCAURdFDhCQkMx3tuLe7jP//h829NC+rqIKNAK8hhGEQjmUyrm+ziVTs50O6jkA6b+J3gSCqpWfiGZxL1yKyhbIQEDQLxj7xTYy7SXoCY1RXbwLXy6OgfdevIbYFdulHaBuI7t3SIY5Nbhm4zAdF/Ow5gvTEEaR/W49Ov2eSIvjuW+Y4tdTCXHML+1XI/A7cwmmdM1nHLZwbl+kPPj9lunELq5LuRWy5hUFyC+uKI+hazabgCJpYcws5gsXS5F8qc02i9C9Jn9ejelHoMkJdhrJ5xb8AAwBmihB0TS21nQAAAABJRU5ErkJggg==) no-repeat right 0}#fatnav .pillar.active .toplevel::after{background-position:0% -5px}#fatnav .pillar.active .expandee{display:-webkit-box;display:-webkit-flex;display:-moz-flex;display:-ms-flex;display:-o-flex;display:flex;-webkit-box-orient:vertical;-webkit-flex-direction:row;-moz-flex-direction:row;-ms-flex-direction:row;-o-flex-direction:row;flex-direction:row}#fatnav .pillar.active .expandee::after{position:absolute;background-image:linear-gradient(bottom, rgba(255,255,255,0) 0%,rgba(211,211,211,0.5) 25%,#d3d3d3 50%,rgba(211,211,211,0.5) 75%,rgba(255,255,255,0) 100%);right:0;top:0;content:'';width:1px !important;height:100%}#fatnav .pillar .expandee{min-height:400px;font-size:0.9em;box-shadow:0 3px 4px rgba(0,0,0,0.12);top:64px}#fatnav .pillar .expandee .submenu{padding:0 20px;border-right:1px solid #e8e8e8}#fatnav .pillar .expandee .submenu:last-child{border:none}#search{margin-right:-4px}#search.active{background:#f5f5f5 url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAyCAMAAABI+VrBAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAALFQTFRF/////f39/v7+/Pz8+/v7+fn56+vr+vr69PT09vb28/Pz9fX1xcXF9/f3+Pj45+fn8PDwycnJ7+/v6enpzc3N19fX8fHx8vLy7u7u6Ojo7Ozs3Nzc5OTk7e3t4uLi2dnZ39/fxsbG29vb0dHR3d3d4ODg4+Pj6urqyMjI09PT5eXl0NDQ1dXV2NjYysrKx8fH5ubmzs7O3t7exMTE4eHh2tray8vLz8/PzMzM1NTU1tbWhgtdWwAAAOFJREFUeNok0NWSxCAURdFDhCQkMx3tuLe7jP//h829NC+rqIKNAK8hhGEQjmUyrm+ziVTs50O6jkA6b+J3gSCqpWfiGZxL1yKyhbIQEDQLxj7xTYy7SXoCY1RXbwLXy6OgfdevIbYFdulHaBuI7t3SIY5Nbhm4zAdF/Ow5gvTEEaR/W49Ov2eSIvjuW+Y4tdTCXHML+1XI/A7cwmmdM1nHLZwbl+kPPj9lunELq5LuRWy5hUFyC+uKI+hazabgCJpYcws5gsXS5F8qc02i9C9Jn9ejelHoMkJdhrJ5xb8AAwBmihB0TS21nQAAAABJRU5ErkJggg==) no-repeat right 0}#search.active .expandee{display:block;top:64px}}@media only screen and (max-width: 580px){#topnav{-webkit-box-orient:vertical;-webkit-flex-direction:column;-moz-flex-direction:column;-ms-flex-direction:column;-o-flex-direction:column;flex-direction:column;height:auto}#fatnav{width:100%;max-height:0;overflow:hidden;background:#f5f5f5}#fatnav.active{max-height:5000px}#fatnav>ul{-webkit-box-flex:1;-webkit-flex:1;-moz-flex:1;-ms-flex:1;-o-flex:1;flex:1;-webkit-box-orient:vertical;-webkit-flex-direction:column;-moz-flex-direction:column;-ms-flex-direction:column;-o-flex-direction:column;flex-direction:column}#fatnav .toplevel{width:100%;height:50px;-webkit-box-align:center;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-o-align-items:center;align-items:center;-webkit-box-pack:1;-webkit-justify-content:center;-moz-justify-content:center;-ms-justify-content:center;-o-justify-content:center;justify-content:center;display:-webkit-inline-flex;display:-moz-inline-flex;display:-ms-inline-flex;display:-o-inline-flex;display:inline-flex}#fatnav .pillar{-webkit-box-orient:vertical;-webkit-flex-direction:column;-moz-flex-direction:column;-ms-flex-direction:column;-o-flex-direction:column;flex-direction:column;padding:0;border-bottom:1px solid #dbdbdb}#fatnav .pillar.active .expandee{display:initial}#fatnav .expandee{position:relative;padding:0;background-color:rgba(229,229,229,0.7)}#fatnav .expandee li.submenu{padding:10px 15px}#fatnav .expandee li.submenu:not(:last-child){border-color:#ccc}#fatnav .expandee li.submenu>ul{background-color:inherit}#logo{height:50px;width:90%}#logo a{-webkit-box-flex:1;-webkit-flex:1;-moz-flex:1;-ms-flex:1;-o-flex:1;flex:1}#logo .collase-icon{display:initial}#search{display:-webkit-box;display:-webkit-flex;display:-moz-flex;display:-ms-flex;display:-o-flex;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-o-align-items:center;align-items:center;-webkit-box-ordinal-group:-1;-webkit-order:-1;-moz-order:-1;-ms-order:-1;-o-order:-1;order:-1;padding:15px 15px 0 15px}#search img{display:none}#search .expandee{display:block}}#gc-pagecontent .g-section h1,#gc-pagecontent .g-section h2,#gc-pagecontent .g-section h3{margin:0}#upcoming-events .screenshot,#featured .screenshot{margin-top:0}#upcoming-events article{border:1px solid #dbdbdb;border-width:0 0 1px 0;padding:20px 0}#upcoming-events article:first-child{padding-top:0}#upcoming-events article:last-child{padding-bottom:0;border:none}#site-sections{background-color:#f5f5f5;padding:20px;text-align:center}#site-sections h2{padding-top:20px}#site-sections h2::before{display:block;content:'';background:url("../../images/bucket-icons.png") 12px 50% no-repeat;width:100px;height:65px;background-size:cover;margin:auto;margin-bottom:20px}#site-sections h2.multidevice::before{background-position:-91px 50%}#site-sections h2.platform::before{background-position:-194px 50%}#developer-news{margin-top:4em}#developer-news .g-content{margin-right:20px}#developer-news h1{margin-bottom:40px !important}@media only screen and (min-width: 580px){#featured{padding-right:30px;padding-bottom:10px;border:1px solid #dbdbdb;border-width:0 1px 0 0}#featured img{margin-bottom:20px}}.pillar-content h1{font-size:42px}.pillar-content>.g-section{padding:3em 0}.pillar-content>.g-section:not(:last-of-type){border-bottom:1px solid #dbdbdb}.pillar-content>.g-section>h2{font-size:30px;margin-bottom:1.5em !important}.pillar-content .article-list article{position:relative;overflow:hidden;width:100%;padding:1.9em;background-color:#f5f5f5;box-shadow:0 2px 4px rgba(0,0,0,0.15),0 0 3px rgba(0,0,0,0.15);line-height:1.5em;margin-bottom:1.5em}.pillar-content .article-list article.new::after{content:'new';background:#2e82c9;position:absolute;-webkit-transform:rotate(45deg);-moz-transform:rotate(45deg);-ms-transform:rotate(45deg);-o-transform:rotate(45deg);transform:rotate(45deg);top:-4px;right:-20px;color:white;font-size:0.9em;width:60px;text-align:center;padding-top:8px}.pillar-content .article-list article p{font-weight:300}.pillar-content #further-resources .g-content h2::before{display:inline-block;content:'';background:url("../../images/further-resources-icons.svg") 0 50% no-repeat;width:50px;height:43px;background-size:cover;margin:auto;margin-bottom:5px;vertical-align:middle}.pillar-content #further-resources .g-content h2.school::before{background-position:0 50%}.pillar-content #further-resources .g-content h2.chat::before{background-position:-54px 50%}.pillar-content #further-resources .g-content h2.puzzle::before{background-position:-108px 50%}@media only screen and (max-width: 580px){.pillar-content>.g-section{padding:2em 0}}@media only screen and (min-width: 580px){.pillar-content .article-list{display:-webkit-box;display:-webkit-flex;display:-moz-flex;display:-ms-flex;display:-o-flex;display:flex;-webkit-flex-wrap:wrap;-moz-flex-wrap:wrap;-ms-flex-wrap:wrap;-o-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-pack:1;-webkit-justify-content:space-between;-moz-justify-content:space-between;-ms-justify-content:space-between;-o-justify-content:space-between;justify-content:space-between;-webkit-box-align:stretch;-webkit-align-items:stretch;-moz-align-items:stretch;-ms-align-items:stretch;-o-align-items:stretch;align-items:stretch}.pillar-content .article-list article{-webkit-box-flex:auto;-webkit-flex:auto;-moz-flex:auto;-ms-flex:auto;-o-flex:auto;flex:auto;margin-right:1.5em;width:45%}.pillar-content .article-list article:nth-child(2n),.pillar-content .article-list article:last-of-type{margin-right:0}}@media only screen and (min-width: 990px){.pillar-content .article-list article{width:30%}.pillar-content .article-list article:nth-child(2n){margin-right:1.5em}.pillar-content .article-list article:nth-child(3n),.pillar-content .article-list article:last-of-type{margin-right:0}}@supports not (flex-wrap: wrap){.pillar-content .article-list{display:block}@media only screen and (min-width: 580px){.pillar-content .article-list article{flex:none;float:left;width:48%}}@media only screen and (min-width: 990px){.pillar-content .article-list article{width:31.8058%}}}.load-more-articles{overflow:hidden;*zoom:1;margin:2em auto 0.3em;text-align:center;width:100%}.load-more-articles a,.load-more-articles a:hover{color:#000;transition:opacity 0.3s ease 0s}.nav-arrow{background-size:48px 48px;background:top center no-repeat;display:inline-block;opacity:0.5;transition:opacity 0.3s ease 0s;padding-top:50px}.nav-arrow:hover{opacity:1}.down-arrow{background-image:url("../../images/down-arrow.png")}.inline-site-toc{line-height:1.3em}.inline-site-toc a{display:-webkit-box;display:-webkit-flex;display:-moz-flex;display:-ms-flex;display:-o-flex;display:flex;padding:0.5em 0}.inline-site-toc a,.inline-site-toc a:link,.inline-site-toc a:visited{color:#aaa;font-weight:normal}.inline-site-toc a:hover,.inline-site-toc a:focus,.inline-site-toc a:link:hover,.inline-site-toc a:link:focus,.inline-site-toc a:visited:hover,.inline-site-toc a:visited:focus{color:#000}.inline-site-toc span .show{display:block;content:"+ or -"}.inline-site-toc li{display:none}.inline-site-toc li .show{display:block;content:"+ or -"}.inline-site-toc li.show,.inline-site-toc li.show>ol>li{display:block}.inline-site-toc li.toplevel span{display:none}.inline-site-toc li.toplevel li{padding-left:1em}.inline-site-toc li.toplevel>ol.toc>li{font-size:15px;margin:0 0;padding:15px 1em;border-bottom:1px solid #dbdbdb}.inline-site-toc li.toplevel>ol>li{cursor:default}.inline-site-toc li.toplevel>ol>li.show{background-color:#f0f0f0}.inline-site-toc li.toplevel>ol>li>ol>li:first-child{padding-top:10px}.inline-site-toc li li a,.inline-site-toc li li a:link,.inline-site-toc li li a:visited{color:#aaa}.inline-site-toc li li a:hover,.inline-site-toc li li a:focus,.inline-site-toc li li a:link:hover,.inline-site-toc li li a:link:focus,.inline-site-toc li li a:visited:hover,.inline-site-toc li li a:visited:focus{color:#000}.inline-site-toc li li.selected>a{font-weight:bold;color:#000}.inline-site-toc .site-related{display:block;background-color:#f5f5f5;padding:0;width:inherit}.inline-site-toc .site-related h3{margin-top:0}.inline-site-toc .site-related li a.active{color:#000}.inline-site-toc #toc{display:block}.inline-site-toc #toc .toplevel>a{font-weight:bold;color:#000}.inline-site-toc #toc .toplevel>a.hastoc::after{content:'+';-webkit-box-flex:1;-webkit-flex:1;-moz-flex:1;-ms-flex:1;-o-flex:1;flex:1;text-align:right}.inline-site-toc #toc .toplevel.active .toc{display:block}.inline-site-toc #toc .toplevel.active>a.hastoc::after{content:""}.inline-site-toc .toc{margin:0;padding:0}.inline-site-toc .toc .toc li{font-size:13px}.inline-site-toc ol.toc ol.toc ol.toc li{margin:0}.inline-toc{line-height:1.3em}.inline-toc a,.inline-toc a:link,.inline-toc a:visited{color:#aaa;font-weight:normal}.inline-toc a:hover,.inline-toc a:focus,.inline-toc a:link:hover,.inline-toc a:link:focus,.inline-toc a:visited:hover,.inline-toc a:visited:focus{color:#000}.inline-toc li li a,.inline-toc li li a:link,.inline-toc li li a:visited{color:#aaa}.inline-toc li li a:hover,.inline-toc li li a:focus,.inline-toc li li a:link:hover,.inline-toc li li a:link:focus,.inline-toc li li a:visited:hover,.inline-toc li li a:visited:focus{color:#000}.inline-toc a{display:-webkit-box;display:-webkit-flex;display:-moz-flex;display:-ms-flex;display:-o-flex;display:flex;padding:0.5em 0}.inline-toc .related{display:block;background-color:#f5f5f5;box-shadow:0 3px 4px rgba(0,0,0,0.12);padding:1em 1em 0.5em 1em;margin-bottom:1em}.inline-toc .related h3{margin-top:0}.inline-toc .related li a.active{color:#000}.inline-toc .related li a:hover{background-image:linear-gradient(205deg, rgba(229,229,229,0.7) 0%,rgba(233,233,233,0.7) 20%,rgba(244,244,244,0.7) 100%)}.inline-toc #toc{display:none}.inline-toc #toc .toplevel>a{font-weight:bold;color:#000}.inline-toc #toc .toplevel>a.hastoc::after{content:'+';-webkit-box-flex:1;-webkit-flex:1;-moz-flex:1;-ms-flex:1;-o-flex:1;flex:1;text-align:right}.inline-toc #toc .toplevel.active .toc{display:block}.inline-toc #toc .toplevel.active>a.hastoc{content:"-"}.inline-toc .toc{margin:0;paddiing:0;border-top:1px solid #dbdbdb}.inline-toc .toc .toc{display:none}.inline-toc .toc .toc li{padding-left:1em;border-bottom:1px solid #dbdbdb}#cc-info{font-style:italic;font-size:0.8em;color:#848484}#cc-info .cc-logo img{width:90px;height:32px}.h1-step{display:block;font-size:0.5em;line-height:150%}.anchor-link-icon{padding-left:1px}@media only screen and (min-width: 580px){.inline-site-toc{float:left;width:175px;overflow-x:hidden}.inline-toc{width:20%;float:right;margin:0 4% 20px 4%;overflow:auto;overflow-x:hidden}.inline-toc #toc{display:block}.article-content{border-right:1px solid #f5f5f5;min-height:750px}.article-content [itemprop="articleBody"]{margin-left:195px}.cc-logo{margin:0 0 0 auto}}@media only screen and (min-width: 581px) and (max-width: 990px){.inline-toc{width:-20%}.inline-site-toc{float:left;width:175px;overflow-x:hidden}}@media only screen and (max-width: 580px){.article-content [itemprop="articleBody"]>.collapsible{height:58px;overflow:hidden}.article-content [itemprop="articleBody"]>.collapsible.active{height:auto}.article-content [itemprop="articleBody"]>.collapsible.active h2::before{content:'-'}.article-content [itemprop="articleBody"]>.collapsible h2{position:relative;margin:0;padding:15px 15px 15px 0;border-top:1px solid #dbdbdb;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.article-content [itemprop="articleBody"]>.collapsible h2::before{position:absolute;right:0;content:'+'}.article-content [itemprop="articleBody"] .related{margin:20px 0}.hidden{display:none}}.api{color:#333;font-size:14px}.api .api-summary td,.api .api-summary th{padding:5px 10px}.api .api-reference .description{margin-left:20px}.api .api-reference table .innerTable{margin:10px 0}.api .api-reference table .innerTable td,.api .api-reference table .innerTable th{padding:5px 10px;border:1px solid #eee}.api .api-reference table .innerTable th{background:none}.api .api-reference table p{margin-top:0.75em;margin-bottom:0.75em}.api .api-reference table p:first-child{margin-top:0}.api .api-reference td,.api .api-reference th{vertical-align:top;border:1px solid #eee}.api .api-reference th{background:#fafafa}.api .api-reference h2{background-color:#e8e8e8;padding:20px;margin-left:-20px;margin-right:-20px}.api .api-reference h3{margin-top:3em}.api .availability{color:#A03}.api table#intro .title{white-space:nowrap} + */article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none;height:0}[hidden],template{display:none}html{font-family:sans-serif;font-size:100%;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}button,input,select,textarea{font-family:sans-serif}body{margin:0}a{background:transparent}a:focus{outline:thin dotted}a:active,a:hover{outline:0}p,pre{margin:1.5em 0}blockquote{margin:1.5em 40px}h1{font-size:2em;line-height:1.5em;margin-top:0.75em;margin-bottom:0.75em}h2{font-size:1.5em;line-height:2em;margin-top:1em;margin-bottom:1em}h3{font-size:1.17em;line-height:1.28205em;margin-top:1.28205em;margin-bottom:1.28205em}h4{font-size:1em;line-height:1.5em;margin-top:1.5em;margin-bottom:1.5em}h5{font-size:0.83em;line-height:1.80723em;margin-top:1.80723em;margin-bottom:1.80723em}h6{font-size:0.67em;line-height:2.23881em;margin-top:2.23881em;margin-bottom:2.23881em}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}hr{-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;height:0}mark{background:#ff0;color:#000}code,kbd,pre,samp{font-family:monospace, serif;_font-family:'courier new', monospace;font-size:1em}pre{white-space:pre;white-space:pre-wrap;word-wrap:break-word}q{quotes:"\201C" "\201D" "\2018" "\2019"}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}dl,menu,ol,ul{margin:1.5em 0}dd{margin:0 0 0 40px}menu,ol,ul{padding:0 0 0 40px}nav ul,nav ol{list-style:none;list-style-image:none}img{border:0;-ms-interpolation-mode:bicubic}svg:not(:root){overflow:hidden}figure{margin:0}form{margin:0}fieldset{margin:0 2px;border-color:#c0c0c0;border-top-width:0.0625em;border-top-style:solid;padding-top:0.4625em;border-bottom-width:0.0625em;border-bottom-style:solid;padding-bottom:0.9125em;border-left-width:0.0625em;border-left-style:solid;padding-left:0.875em;border-right-width:0.0625em;border-right-style:solid;padding-right:0.875em}legend{border:0;padding:0;*margin-left:-7px}button,input,select,textarea{font-family:inherit;font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}button,input{line-height:normal}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer;*overflow:visible}button[disabled],html input[disabled]{cursor:default}input[type="checkbox"],input[type="radio"]{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;padding:0;*height:13px;*width:13px}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}textarea{overflow:auto;vertical-align:top}table{border-collapse:collapse;border-spacing:0}html{font-size:100%;line-height:1.5em}html{font-size:100%;line-height:1.5em}.g-section:after{content:".";display:block;height:0;clear:both;visibility:hidden}.g-unit .g-section:after{clear:none}.g-unit .g-section{width:100%;overflow:hidden}.g-section,.g-unit{zoom:1}.g-split>.g-unit{float:right;text-align:right}.g-split>.g-first{float:left;text-align:left}.g-tpl-160 .g-unit,.g-unit .g-tpl-160 .g-unit,.g-unit .g-unit .g-tpl-160 .g-unit,.g-unit .g-unit .g-unit .g-tpl-160 .g-unit,.g-unit .g-unit .g-unit .g-unit .g-tpl-160 .g-unit,.g-unit .g-unit .g-unit .g-unit .g-unit .g-tpl-160 .g-unit{display:block;margin:0 0 0 160px;width:auto;float:none}.g-tpl-160 .g-first,.g-unit .g-tpl-160 .g-first,.g-unit .g-unit .g-tpl-160 .g-first,.g-unit .g-unit .g-unit .g-tpl-160 .g-first,.g-unit .g-unit .g-unit .g-unit .g-tpl-160 .g-first,.g-unit .g-unit .g-unit .g-unit .g-unit .g-tpl-160 .g-first{display:block;margin:0;width:160px;float:left}.g-tpl-25-75 .g-unit,.g-unit .g-tpl-25-75 .g-unit,.g-unit .g-unit .g-tpl-25-75 .g-unit,.g-unit .g-unit .g-unit .g-tpl-25-75 .g-unit,.g-unit .g-unit .g-unit .g-unit .g-tpl-25-75 .g-unit,.g-unit .g-unit .g-unit .g-unit .g-unit .g-tpl-25-75 .g-unit{width:74.999%;float:right;display:inline;margin:0}.g-tpl-25-75 .g-first,.g-unit .g-tpl-25-75 .g-first,.g-unit .g-unit .g-tpl-25-75 .g-first,.g-unit .g-unit .g-unit .g-tpl-25-75 .g-first,.g-unit .g-unit .g-unit .g-unit .g-tpl-25-75 .g-first,.g-unit .g-unit .g-unit .g-unit .g-unit .g-tpl-25-75 .g-first{width:24.999%;float:left;display:inline;margin:0}.g-tpl-75-25 .g-unit,.g-unit .g-tpl-75-25 .g-unit,.g-unit .g-unit .g-tpl-75-25 .g-unit,.g-unit .g-unit .g-unit .g-tpl-75-25 .g-unit,.g-unit .g-unit .g-unit .g-unit .g-tpl-75-25 .g-unit,.g-unit .g-unit .g-unit .g-unit .g-unit .g-tpl-75-25 .g-unit{width:24.999%;float:right;display:inline;margin:0}.g-tpl-75-25 .g-first,.g-unit .g-tpl-75-25 .g-first,.g-unit .g-unit .g-tpl-75-25 .g-first,.g-unit .g-unit .g-unit .g-tpl-75-25 .g-first,.g-unit .g-unit .g-unit .g-unit .g-tpl-75-25 .g-first,.g-unit .g-unit .g-unit .g-unit .g-unit .g-tpl-75-25 .g-first{width:74.999%;float:left;display:inline;margin:0}.g-tpl-33-67 .g-unit,.g-unit .g-tpl-33-67 .g-unit,.g-unit .g-unit .g-tpl-33-67 .g-unit,.g-unit .g-unit .g-unit .g-tpl-33-67 .g-unit,.g-unit .g-unit .g-unit .g-unit .g-tpl-33-67 .g-unit,.g-unit .g-unit .g-unit .g-unit .g-unit .g-tpl-33-67 .g-unit{width:66.999%;float:right;display:inline;margin:0}.g-tpl-33-67 .g-first,.g-unit .g-tpl-33-67 .g-first,.g-unit .g-unit .g-tpl-33-67 .g-first,.g-unit .g-unit .g-unit .g-tpl-33-67 .g-first,.g-unit .g-unit .g-unit .g-unit .g-tpl-33-67 .g-first,.g-unit .g-unit .g-unit .g-unit .g-unit .g-tpl-33-67 .g-first{width:32.999%;float:left;display:inline;margin:0}.g-tpl-67-33 .g-unit,.g-unit .g-tpl-67-33 .g-unit,.g-unit .g-unit .g-tpl-67-33 .g-unit,.g-unit .g-unit .g-unit .g-tpl-67-33 .g-unit,.g-unit .g-unit .g-unit .g-unit .g-tpl-67-33 .g-unit,.g-unit .g-unit .g-unit .g-unit .g-unit .g-tpl-67-33 .g-unit{width:32.999%;float:right;display:inline;margin:0}.g-tpl-67-33 .g-first,.g-unit .g-tpl-67-33 .g-first,.g-unit .g-unit .g-tpl-67-33 .g-first,.g-unit .g-unit .g-unit .g-tpl-67-33 .g-first,.g-unit .g-unit .g-unit .g-unit .g-tpl-67-33 .g-first,.g-unit .g-unit .g-unit .g-unit .g-unit .g-tpl-67-33 .g-first{width:66.999%;float:left;display:inline;margin:0}.g-tpl-50-50 .g-unit,.g-unit .g-tpl-50-50 .g-unit,.g-unit .g-unit .g-tpl-50-50 .g-unit,.g-unit .g-unit .g-unit .g-tpl-50-50 .g-unit,.g-unit .g-unit .g-unit .g-unit .g-tpl-50-50 .g-unit,.g-unit .g-unit .g-unit .g-unit .g-unit .g-tpl-50-50 .g-unit{width:49.999%;float:right;display:inline;margin:0}.g-tpl-50-50 .g-first,.g-unit .g-tpl-50-50 .g-first,.g-unit .g-unit .g-tpl-50-50 .g-first,.g-unit .g-unit .g-unit .g-tpl-50-50 .g-first,.g-unit .g-unit .g-unit .g-unit .g-tpl-50-50 .g-first,.g-unit .g-unit .g-unit .g-unit .g-unit .g-tpl-50-50 .g-first{width:49.999%;float:left;display:inline;margin:0}.g-tpl-nest .g-unit{float:left;width:auto;display:inline;margin:0}.g-tpl-nest-alt .g-unit{float:right;width:auto;display:inline;margin:0}.g-content{margin-right:30px}.g-last .g-content{margin-right:0}@media only screen and (max-width: 580px){.g-unit.g-unit{float:none !important}.g-content{margin-right:0}}*{padding:0;margin:0;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}html,body{overflow-x:hidden;overflow-y:auto}img{max-width:100%}#gc-container{max-width:870px;margin:auto;width:90%}#gc-pagecontent>.g-section{margin:40px 0}main{margin-bottom:50px;position:relative}footer[role="contentinfo"]{padding:40px 0 50px}@media only screen and (max-width: 580px){#gc-container{width:auto}#gc-pagecontent{margin:auto;width:90%}#gc-pagecontent>.g-section{margin:20px 0}footer[role="contentinfo"]{padding:20px 30px}}@media only screen and (min-width: 581px) and (max-width: 990px){#gc-container{width:95%}}figure{margin:20px 0}figure img{border:1px solid #dbdbdb}table{width:100%;border-collapse:collapse;margin:2em 0;line-height:1.5em}table caption{margin-bottom:1em;text-align:left;font-weight:bold}th{border:1px solid #dbdbdb;font-weight:bold;background:#e8e8e8}tr{border-bottom:1px solid #dbdbdb}table+tr{border-top:1px solid #dbdbdb}td,th{padding:1em 1.5em;text-align:left;border:1px solid #dbdbdb}pre{background-color:#f7f7f7;box-shadow:0 2px 4px rgba(0,0,0,0.15),0 0 3px rgba(0,0,0,0.15);margin:1em 0 0 0;padding:.99em;position:relative;overflow-x:auto;word-wrap:normal;white-space:pre;font-size:0.95em;line-height:1.8em}pre a{text-decoration:underline !important}pre b{background:yellow;font-weight:normal}pre strike{text-decoration:none;background-image:linear-gradient(rgba(0,0,0,0) 7px,#cc1f1f 7px,#cc1f1f 9px,rgba(0,0,0,0) 9px)}pre[data-filename]::after{visibility:hidden}pre[data-filename]:hover::after{visibility:visible}.element-invisible{position:absolute !important;height:1px;width:1px;overflow:hidden;clip:rect(1px 1px 1px 1px);clip:rect(1px, 1px, 1px, 1px)}.hidden{display:none}.label{color:inherit;text-transform:uppercase;margin-bottom:5px;font-size:11.2px;font-weight:bold}.published{font-size:11.2px;font-style:italic;color:#bebebe;line-height:16.8px}.description{margin:20px 0}.description:last-child{margin-bottom:0}.span-full{background:#f5f5f5;position:relative;padding:3em 0}.span-full::before,.span-full::after{content:'';height:100%;width:100%;top:0;position:absolute;background:#f5f5f5;z-index:-1}.span-full::before{left:-100%}.span-full::after{left:100%}.button{background:#0370ea;background-image:linear-gradient(to bottom, #008dfd 0%,#0370ea 100%);border:1px solid #076bd2;border-radius:3px;color:#fff !important;display:inline-block;font-size:13px;font-weight:700;line-height:1.3;padding:5px 20px;text-align:center;text-decoration:none !important;text-shadow:1px 1px 1px #076bd2}.button:hover{background-image:linear-gradient(to bottom, #008dfd 30%,#0370ea 100%);cursor:pointer}.button a{color:inherit !important}.button-alt{background:#eee;background-image:linear-gradient(to top, #dcdcdc 46%,#fafafa 87%);border:1px solid #d6d6d6;border-radius:3px;color:#333 !important;display:inline-block;font-size:12px;font-weight:700;line-height:24px;padding:0 15px;text-align:center;text-decoration:none !important;text-shadow:none}.button-alt:hover{background-image:linear-gradient(to top, #dcdcdc 20%,#fafafa 87%);cursor:pointer}.google-button{background-color:#f5f5f5;border-radius:2px 0 0 0;border:1px solid rgba(0,0,0,0.1);padding:5px 12px;text-align:center;white-space:nowrap}.google-button:hover{border-color:#c6c6c6;box-shadow:0 -1px 1px rgba(0,0,0,0.1)}.google-button:active{background-color:#f1f1f1;box-shadow:inset 0 0px 2px rgba(0,0,0,0.2)}.screenshot,.screenshot img{margin:1em 0}.video-container{position:relative;padding-bottom:56.25%;padding-top:30px;height:0;overflow:hidden;margin:0 0 20px 0}.video-container iframe,.video-container object,.video-container embed{position:absolute;top:0;left:0;width:100%;height:100%}p.note,p.caution,p.warning,div.note,div.caution,div.warning,aside.note,aside.caution,aside.warning{background-color:#f5f5f5;border-bottom:1px solid;border-top:1px solid;overflow:hidden;max-width:85%;padding:1em}p.note,div.note,aside.note{border-color:#36C}p.caution,div.caution,aside.caution{border-color:#FC3}p.warning,div.warning,aside.warning{border-color:#A03}p.warning em,p.warning strong,div.warning em,div.warning strong,aside.warning em,aside.warning strong{color:#A03}.permalink{display:none;margin-left:5px}.has-permalink:hover .permalink{display:initial}.no-permalink .permalink{display:none !important}#gc-footer .links a{margin-right:20px}#gc-footer #cc-info{font-size:11.2px}#social-buttons{display:-webkit-box;display:-webkit-flex;display:-moz-flex;display:-ms-flex;display:-o-flex;display:flex;-webkit-box-pack:1;-webkit-justify-content:flex-end;-moz-justify-content:flex-end;-ms-justify-content:flex-end;-o-justify-content:flex-end;justify-content:flex-end;-webkit-box-align:center;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-o-align-items:center;align-items:center}#social-buttons>*{margin-left:10px}#social-buttons img{margin:-4px 0 0 1px}@media only screen and (max-width: 580px){.more-section .g-last .g-content{padding-bottom:0;border:none}.more-section .g-content{border:1px solid #dbdbdb;border-width:0 0 1px 0;padding-bottom:20px;margin-bottom:20px}#gc-footer .links a{display:inline-block}}#scroll-to-top,#send-feedback{border-bottom:none;bottom:0;position:fixed;z-index:5}#scroll-to-top{border-left:0;left:0}#send-feedback{border-right:0;right:0}html{font-family:"Open Sans",Arial,"Lucida Grande",sans-serif;color:#777}body{font-size:13px;color:#777}h1,h2,h3,h4,h5,h6{font-family:"Open Sans",Arial,"Lucida Grande",sans-serif;font-weight:600;color:#000}h1,h2{font-weight:300}h1{font-size:2.625em;line-height:1.14286em}h1+h1{margin-top:0em}h2{font-size:1.875em;line-height:1.6em;margin-top:1.6em;margin-bottom:0em;line-height:1.12em}h3{font-size:1.125em;line-height:1.33333em;margin-top:1.33333em;margin-bottom:0.53333em;line-height:1.12em}h4{font-size:1.1em;line-height:1.36364em;margin-top:0em;margin-bottom:0em}h5{font-size:1em;line-height:1.5em;margin-top:0em;margin-bottom:0em}h6{font-size:1em;line-height:1.5em;margin-top:0em;margin-bottom:0em}p{margin:1.5em 0}p.noindent,p.caption p{text-indent:0}p.caption{text-align:left;margin-top:9px;font-weight:bold}.lightbox p.caption{color:#fff}a,a:link,a:visited{color:#39c;font-weight:bold;text-decoration:none;word-wrap:break-word;transition:opacity 0.3s ease 0s}a:hover,a:focus,a:link:hover,a:link:focus,a:visited:hover,a:visited:focus{color:#39f}a.section-anchor{display:block;padding-top:3.33em}footer[role="contentinfo"]{font-size:0.84615385em}footer[role="contentinfo"] a,footer[role="contentinfo"] a:link,footer[role="contentinfo"] a:visited{color:#999;font-weight:normal;font-weight:600;text-decoration:none;word-wrap:break-word}footer[role="contentinfo"] a:hover,footer[role="contentinfo"] a:focus,footer[role="contentinfo"] a:link:hover,footer[role="contentinfo"] a:link:focus,footer[role="contentinfo"] a:visited:hover,footer[role="contentinfo"] a:visited:focus{color:#39f}table{font-size:13px}td dl{margin:0.4em 0}td dt{margin:0 0 0.4em 0}em{padding-right:2px}img{vertical-align:middle}figcaption{font-family:"Open Sans",Arial,"Lucida Grande",sans-serif;color:#aaa}blockquote{margin:0.75em 0.8em}cite{margin:0.75em 0.8em;color:#c3c3c3;font-style:normal}canvas{background:#fff;margin:1.5em 0}.code,code,pre{color:#080;font-family:"Source Code Pro",sans-serif}a>code{color:#39c}pre{margin:2em 0;word-wrap:break-word;position:relative}pre[data-filename]::after{content:attr(data-filename);background-color:#aaa;color:#fff;padding:2px 12px;position:absolute;right:0;top:0}pre a{text-decoration:underline}.static-code-container{line-height:1em;clear:both}code,kbd,samp{margin:1.5em 0;line-height:1em}dl,menu,ol,ul,.item-list ul{margin:0.8em 0}ul{padding-left:1.28em}ol{padding-left:1.52em}hr{height:1px;border:0;border-bottom:1px solid #dbdbdb;padding-bottom:-1px;margin:1.5em 0}[data-list-item]{display:list-item}.kbd{background-color:#f7f7f7;border:1px solid #ccc;color:#333;font-size:11px;line-height:1.4;text-shadow:0 1px 0 #fff;font-family:Arial,Helvetica,sans-serif;display:inline-block;padding:0.1em 0.6em;margin:0 0.1em;white-space:nowrap;box-shadow:0 1px 0px rgba(0,0,0,0.2),0 0 0 2px #fff inset;border-radius:3px}#topnav{display:-webkit-box;display:-webkit-flex;display:-moz-flex;display:-ms-flex;display:-o-flex;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-o-align-items:center;align-items:center;height:64px;position:relative}#logo{display:-webkit-box;display:-webkit-flex;display:-moz-flex;display:-ms-flex;display:-o-flex;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-o-align-items:center;align-items:center;-webkit-user-select:none;-moz-user-select:none;-o-user-select:none;-ms-user-select:none;user-select:none}#logo a{display:-webkit-box;display:-webkit-flex;display:-moz-flex;display:-ms-flex;display:-o-flex;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-o-align-items:center;align-items:center;color:#828282;font-size:2em;font-weight:400;letter-spacing:-1px}#logo a img{margin-bottom:-4px;height:40px;width:123px}#logo .collase-icon{display:none;background:url("../../images/burger-icon.png") 50% 100% no-repeat;background-size:cover;width:20px;height:20px}#logo .collase-icon.active{background-position:50% 0}#fatnav{height:100%;display:-webkit-box;display:-webkit-flex;display:-moz-flex;display:-ms-flex;display:-o-flex;display:flex;-webkit-box-pack:1;-webkit-justify-content:flex-end;-moz-justify-content:flex-end;-ms-justify-content:flex-end;-o-justify-content:flex-end;justify-content:flex-end;-webkit-box-flex:1;-webkit-flex:1;-moz-flex:1;-ms-flex:1;-o-flex:1;flex:1;white-space:nowrap}#fatnav li{list-style:none}#fatnav>ul{display:-webkit-box;display:-webkit-flex;display:-moz-flex;display:-ms-flex;display:-o-flex;display:flex;padding:0;margin:0}#fatnav .toplevel{color:#aaa;font-weight:600;text-transform:uppercase;-webkit-user-select:none;-moz-user-select:none;-o-user-select:none;-ms-user-select:none;user-select:none}#fatnav .toplevel::after{content:'';background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAPJJREFUeNpiyc/Pn8XAwDATiM8yEAaMQBwBxHxMQMIdiE8D8Vog1sGjyQGqbhkQK4A0PoKaFATEF4F4MRCrImnQBuJtQLwfiI2hYk9AGl2AuB2I/wAxiB8DxNeAeA4QzwXiS0DsCdXwHIj9gHgqSOFPIK4CYksgvgJVwALEyUCcBDWMAeoSkO2bGZAEQeAM1CmtUNth4BkQ+wJxHBC/hwkyoQXALyCuAWILIL4MxIugAbYFI3iNZ54BR4fNtcXo0QEy9B+ywBGtWMzoAAquBWLk6EDXhBIdLNDokINGRwBQAUiiCYhvI0VHN1LIjpjoAAgwAMoSTlKlzAY4AAAAAElFTkSuQmCC) no-repeat;background-size:9px;display:inline-block;height:5px;width:14px;margin-left:10px;margin-bottom:2px}#fatnav .pillar{display:-webkit-box;display:-webkit-flex;display:-moz-flex;display:-ms-flex;display:-o-flex;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-o-align-items:center;align-items:center;padding:0 20px;cursor:pointer;z-index:1002}#fatnav .expandee{display:none;position:absolute;z-index:1001;left:0;width:100%;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;background-color:#f5f5f5;padding:20px 0;cursor:initial;margin:0}#fatnav .expandee a{font-weight:600;padding:0.5em 0;display:block;color:#828282}#fatnav .expandee a:hover{background-image:linear-gradient(205deg, rgba(229,229,229,0.7) 0%,rgba(233,233,233,0.7) 20%,rgba(244,244,244,0.7) 100%)}#fatnav .expandee a.highlight{color:#000;background-image:linear-gradient(205deg, rgba(229,229,229,0.7) 0%,rgba(233,233,233,0.7) 20%,rgba(244,244,244,0.7) 100%)}#fatnav .expandee li{white-space:nowrap}#fatnav .expandee li.submenu{color:#333;font-size:1.1em;font-weight:bold;-webkit-box-flex:1;-webkit-flex:1;-moz-flex:1;-ms-flex:1;-o-flex:1;flex:1}#fatnav .expandee li.submenu.active{background-image:linear-gradient(205deg, rgba(229,229,229,0.7) 0%,rgba(233,233,233,0.7) 20%,rgba(244,244,244,0.7) 100%)}#fatnav .expandee li.submenu>ul{font-size:0.8em;padding:15px 0 0 0;margin:0}#fatnav .expandee li.submenu .category{border-bottom:1px solid #e8e8e8}#fatnav .expandee li.submenu .category:last-child{border:none}#fatnav .expandee li.submenu .category a{overflow:hidden;text-overflow:ellipsis}#fatnav .expandee li.submenu .category>ul{display:none}#fatnav .expandee li.submenu .category ul{padding:0}#search{display:-webkit-inline-flex;display:-moz-inline-flex;display:-ms-inline-flex;display:-o-inline-flex;display:inline-flex;-webkit-align-self:stretch;-moz-align-self:stretch;-ms-align-self:stretch;-o-align-self:stretch;align-self:stretch;-webkit-box-align:center;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-o-align-items:center;align-items:center;width:auto;padding:0 20px;cursor:pointer}#search img{height:16px;width:16px;-webkit-user-select:none;-moz-user-select:none;-o-user-select:none;-ms-user-select:none;user-select:none}#search .expandee{padding:20px}#search .expandee input[type="search"]{width:100%;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;background:url("../../images/search.png") no-repeat 15px 55%;background-size:20px;background-color:white;border:1px solid #dbdbdb;padding:10px 10px 10px 40px;font-size:1.4em;-webkit-box-flex:1;-webkit-flex:1;-moz-flex:1;-ms-flex:1;-o-flex:1;flex:1;font-family:inherit;font-weight:300}@media only screen and (min-width: 580px){#topnav{padding:15px 0 0}#fatnav .pillar.highlight .toplevel{color:#000}#fatnav .pillar.active{background:#f5f5f5 url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAyCAMAAABI+VrBAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAALFQTFRF/////f39/v7+/Pz8+/v7+fn56+vr+vr69PT09vb28/Pz9fX1xcXF9/f3+Pj45+fn8PDwycnJ7+/v6enpzc3N19fX8fHx8vLy7u7u6Ojo7Ozs3Nzc5OTk7e3t4uLi2dnZ39/fxsbG29vb0dHR3d3d4ODg4+Pj6urqyMjI09PT5eXl0NDQ1dXV2NjYysrKx8fH5ubmzs7O3t7exMTE4eHh2tray8vLz8/PzMzM1NTU1tbWhgtdWwAAAOFJREFUeNok0NWSxCAURdFDhCQkMx3tuLe7jP//h829NC+rqIKNAK8hhGEQjmUyrm+ziVTs50O6jkA6b+J3gSCqpWfiGZxL1yKyhbIQEDQLxj7xTYy7SXoCY1RXbwLXy6OgfdevIbYFdulHaBuI7t3SIY5Nbhm4zAdF/Ow5gvTEEaR/W49Ov2eSIvjuW+Y4tdTCXHML+1XI/A7cwmmdM1nHLZwbl+kPPj9lunELq5LuRWy5hUFyC+uKI+hazabgCJpYcws5gsXS5F8qc02i9C9Jn9ejelHoMkJdhrJ5xb8AAwBmihB0TS21nQAAAABJRU5ErkJggg==) no-repeat right 0}#fatnav .pillar.active .toplevel::after{background-position:0% -5px}#fatnav .pillar.active .expandee{display:-webkit-box;display:-webkit-flex;display:-moz-flex;display:-ms-flex;display:-o-flex;display:flex;-webkit-box-orient:vertical;-webkit-flex-direction:row;-moz-flex-direction:row;-ms-flex-direction:row;-o-flex-direction:row;flex-direction:row}#fatnav .pillar.active .expandee::after{position:absolute;background-image:linear-gradient(to top, rgba(255,255,255,0) 0%,rgba(211,211,211,0.5) 25%,#d3d3d3 50%,rgba(211,211,211,0.5) 75%,rgba(255,255,255,0) 100%);right:0;top:0;content:'';width:1px !important;height:100%}#fatnav .pillar .expandee{min-height:400px;font-size:0.9em;box-shadow:0 3px 4px rgba(0,0,0,0.12);top:64px}#fatnav .pillar .expandee .submenu{padding:0 20px;border-right:1px solid #e8e8e8}#fatnav .pillar .expandee .submenu:last-child{border:none}#search{margin-right:-4px}#search.active{background:#f5f5f5 url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAyCAMAAABI+VrBAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAALFQTFRF/////f39/v7+/Pz8+/v7+fn56+vr+vr69PT09vb28/Pz9fX1xcXF9/f3+Pj45+fn8PDwycnJ7+/v6enpzc3N19fX8fHx8vLy7u7u6Ojo7Ozs3Nzc5OTk7e3t4uLi2dnZ39/fxsbG29vb0dHR3d3d4ODg4+Pj6urqyMjI09PT5eXl0NDQ1dXV2NjYysrKx8fH5ubmzs7O3t7exMTE4eHh2tray8vLz8/PzMzM1NTU1tbWhgtdWwAAAOFJREFUeNok0NWSxCAURdFDhCQkMx3tuLe7jP//h829NC+rqIKNAK8hhGEQjmUyrm+ziVTs50O6jkA6b+J3gSCqpWfiGZxL1yKyhbIQEDQLxj7xTYy7SXoCY1RXbwLXy6OgfdevIbYFdulHaBuI7t3SIY5Nbhm4zAdF/Ow5gvTEEaR/W49Ov2eSIvjuW+Y4tdTCXHML+1XI/A7cwmmdM1nHLZwbl+kPPj9lunELq5LuRWy5hUFyC+uKI+hazabgCJpYcws5gsXS5F8qc02i9C9Jn9ejelHoMkJdhrJ5xb8AAwBmihB0TS21nQAAAABJRU5ErkJggg==) no-repeat right 0}#search.active .expandee{display:block;top:64px}}@media only screen and (max-width: 580px){#topnav{-webkit-box-orient:vertical;-webkit-flex-direction:column;-moz-flex-direction:column;-ms-flex-direction:column;-o-flex-direction:column;flex-direction:column;height:auto}#fatnav{width:100%;max-height:0;overflow:hidden;background:#f5f5f5}#fatnav.active{max-height:5000px}#fatnav>ul{-webkit-box-flex:1;-webkit-flex:1;-moz-flex:1;-ms-flex:1;-o-flex:1;flex:1;-webkit-box-orient:vertical;-webkit-flex-direction:column;-moz-flex-direction:column;-ms-flex-direction:column;-o-flex-direction:column;flex-direction:column}#fatnav .toplevel{width:100%;height:50px;-webkit-box-align:center;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-o-align-items:center;align-items:center;-webkit-box-pack:1;-webkit-justify-content:center;-moz-justify-content:center;-ms-justify-content:center;-o-justify-content:center;justify-content:center;display:-webkit-inline-flex;display:-moz-inline-flex;display:-ms-inline-flex;display:-o-inline-flex;display:inline-flex}#fatnav .pillar{-webkit-box-orient:vertical;-webkit-flex-direction:column;-moz-flex-direction:column;-ms-flex-direction:column;-o-flex-direction:column;flex-direction:column;padding:0;border-bottom:1px solid #dbdbdb}#fatnav .pillar.active .expandee{display:initial}#fatnav .expandee{position:relative;padding:0;background-color:rgba(229,229,229,0.7)}#fatnav .expandee li.submenu{padding:10px 15px}#fatnav .expandee li.submenu:not(:last-child){border-color:#ccc}#fatnav .expandee li.submenu>ul{background-color:inherit}#logo{height:50px;width:90%}#logo a{-webkit-box-flex:1;-webkit-flex:1;-moz-flex:1;-ms-flex:1;-o-flex:1;flex:1}#logo .collase-icon{display:initial}#search{display:-webkit-box;display:-webkit-flex;display:-moz-flex;display:-ms-flex;display:-o-flex;display:flex;-webkit-box-align:center;-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;-o-align-items:center;align-items:center;-webkit-box-ordinal-group:-1;-webkit-order:-1;-moz-order:-1;-ms-order:-1;-o-order:-1;order:-1;padding:15px 15px 0 15px}#search img{display:none}#search .expandee{display:block}}#gc-pagecontent .g-section h1,#gc-pagecontent .g-section h2,#gc-pagecontent .g-section h3{margin:0}#upcoming-events .screenshot,#featured .screenshot{margin-top:0}#upcoming-events article{border:1px solid #dbdbdb;border-width:0 0 1px 0;padding:20px 0}#upcoming-events article:first-child{padding-top:0}#upcoming-events article:last-child{padding-bottom:0;border:none}#site-sections{background-color:#f5f5f5;padding:20px;text-align:center}#site-sections h2{padding-top:20px}#site-sections h2::before{display:block;content:'';background:url("../../images/bucket-icons.png") 12px 50% no-repeat;width:100px;height:65px;background-size:cover;margin:auto;margin-bottom:20px}#site-sections h2.multidevice::before{background-position:-91px 50%}#site-sections h2.platform::before{background-position:-194px 50%}#developer-news{margin-top:4em}#developer-news .g-content{margin-right:20px}#developer-news h1{margin-bottom:40px !important}@media only screen and (min-width: 580px){#featured{padding-right:30px;padding-bottom:10px;border:1px solid #dbdbdb;border-width:0 1px 0 0}#featured img{margin-bottom:20px}}.pillar-content h1{font-size:42px}.pillar-content>.g-section{padding:3em 0}.pillar-content>.g-section:not(:last-of-type){border-bottom:1px solid #dbdbdb}.pillar-content>.g-section>h2{font-size:30px;margin-bottom:1.5em !important}.pillar-content .article-list article{position:relative;overflow:hidden;width:100%;padding:1.9em;background-color:#f5f5f5;box-shadow:0 2px 4px rgba(0,0,0,0.15),0 0 3px rgba(0,0,0,0.15);line-height:1.5em;margin-bottom:1.5em}.pillar-content .article-list article.new::after{content:'new';background:#2e82c9;position:absolute;-moz-transform:rotate(45deg);-ms-transform:rotate(45deg);-webkit-transform:rotate(45deg);transform:rotate(45deg);top:-4px;right:-20px;color:white;font-size:0.9em;width:60px;text-align:center;padding-top:8px}.pillar-content .article-list article p{font-weight:300}.pillar-content #further-resources .g-content h2::before{display:inline-block;content:'';background:url("../../images/further-resources-icons.svg") 0 50% no-repeat;width:50px;height:43px;background-size:cover;margin:auto;margin-bottom:5px;vertical-align:middle}.pillar-content #further-resources .g-content h2.school::before{background-position:0 50%}.pillar-content #further-resources .g-content h2.chat::before{background-position:-54px 50%}.pillar-content #further-resources .g-content h2.puzzle::before{background-position:-108px 50%}@media only screen and (max-width: 580px){.pillar-content>.g-section{padding:2em 0}}@media only screen and (min-width: 580px){.pillar-content .article-list{display:-webkit-box;display:-webkit-flex;display:-moz-flex;display:-ms-flex;display:-o-flex;display:flex;-webkit-flex-wrap:wrap;-moz-flex-wrap:wrap;-ms-flex-wrap:wrap;-o-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-pack:1;-webkit-justify-content:space-between;-moz-justify-content:space-between;-ms-justify-content:space-between;-o-justify-content:space-between;justify-content:space-between;-webkit-box-align:stretch;-webkit-align-items:stretch;-moz-align-items:stretch;-ms-align-items:stretch;-o-align-items:stretch;align-items:stretch}.pillar-content .article-list article{-webkit-box-flex:auto;-webkit-flex:auto;-moz-flex:auto;-ms-flex:auto;-o-flex:auto;flex:auto;margin-right:1.5em;width:45%}.pillar-content .article-list article:nth-child(2n),.pillar-content .article-list article:last-of-type{margin-right:0}}@media only screen and (min-width: 990px){.pillar-content .article-list article{width:30%}.pillar-content .article-list article:nth-child(2n){margin-right:1.5em}.pillar-content .article-list article:nth-child(3n),.pillar-content .article-list article:last-of-type{margin-right:0}}@supports not (flex-wrap: wrap){.pillar-content .article-list{display:block}@media only screen and (min-width: 580px){.pillar-content .article-list article{flex:none;float:left;width:48%}}@media only screen and (min-width: 990px){.pillar-content .article-list article{width:31.8058%}}}.load-more-articles{overflow:hidden;*zoom:1;margin:2em auto 0.3em;text-align:center;width:100%}.load-more-articles a,.load-more-articles a:hover{color:#000;transition:opacity 0.3s ease 0s}.nav-arrow{background-size:48px 48px;background:top center no-repeat;display:inline-block;opacity:0.5;transition:opacity 0.3s ease 0s;padding-top:50px}.nav-arrow:hover{opacity:1}.down-arrow{background-image:url("../../images/down-arrow.png")}.inline-site-toc{line-height:1.3em}.inline-site-toc a{display:-webkit-box;display:-webkit-flex;display:-moz-flex;display:-ms-flex;display:-o-flex;display:flex;padding:0.5em 0}.inline-site-toc a,.inline-site-toc a:link,.inline-site-toc a:visited{color:#aaa;font-weight:normal}.inline-site-toc a:hover,.inline-site-toc a:focus,.inline-site-toc a:link:hover,.inline-site-toc a:link:focus,.inline-site-toc a:visited:hover,.inline-site-toc a:visited:focus{color:#000}.inline-site-toc span .show{display:block;content:"+ or -"}.inline-site-toc li{display:none}.inline-site-toc li .show{display:block;content:"+ or -"}.inline-site-toc li.show,.inline-site-toc li.show>ol>li{display:block}.inline-site-toc li.toplevel span{display:none}.inline-site-toc li.toplevel li{padding-left:1em}.inline-site-toc li.toplevel>ol.toc>li{font-size:15px;margin:0 0;padding:15px 1em;border-bottom:1px solid #dbdbdb}.inline-site-toc li.toplevel>ol>li{cursor:default}.inline-site-toc li.toplevel>ol>li.show{background-color:#f0f0f0}.inline-site-toc li.toplevel>ol>li>ol>li:first-child{padding-top:10px}.inline-site-toc li li a,.inline-site-toc li li a:link,.inline-site-toc li li a:visited{color:#aaa}.inline-site-toc li li a:hover,.inline-site-toc li li a:focus,.inline-site-toc li li a:link:hover,.inline-site-toc li li a:link:focus,.inline-site-toc li li a:visited:hover,.inline-site-toc li li a:visited:focus{color:#000}.inline-site-toc li li.selected>a{font-weight:bold;color:#000}.inline-site-toc .site-related{display:block;background-color:#f5f5f5;padding:0;width:inherit}.inline-site-toc .site-related h3{margin-top:0}.inline-site-toc .site-related li a.active{color:#000}.inline-site-toc #toc{display:block}.inline-site-toc #toc .toplevel>a{font-weight:bold;color:#000}.inline-site-toc #toc .toplevel>a.hastoc::after{content:'+';-webkit-box-flex:1;-webkit-flex:1;-moz-flex:1;-ms-flex:1;-o-flex:1;flex:1;text-align:right}.inline-site-toc #toc .toplevel.active .toc{display:block}.inline-site-toc #toc .toplevel.active>a.hastoc::after{content:""}.inline-site-toc .toc{margin:0;padding:0}.inline-site-toc .toc .toc li{font-size:13px}.inline-site-toc ol.toc ol.toc ol.toc li{margin:0}.inline-toc{line-height:1.3em}.inline-toc a,.inline-toc a:link,.inline-toc a:visited{color:#aaa;font-weight:normal}.inline-toc a:hover,.inline-toc a:focus,.inline-toc a:link:hover,.inline-toc a:link:focus,.inline-toc a:visited:hover,.inline-toc a:visited:focus{color:#000}.inline-toc li li a,.inline-toc li li a:link,.inline-toc li li a:visited{color:#aaa}.inline-toc li li a:hover,.inline-toc li li a:focus,.inline-toc li li a:link:hover,.inline-toc li li a:link:focus,.inline-toc li li a:visited:hover,.inline-toc li li a:visited:focus{color:#000}.inline-toc a{display:-webkit-box;display:-webkit-flex;display:-moz-flex;display:-ms-flex;display:-o-flex;display:flex;padding:0.5em 0}.inline-toc .related{display:block;background-color:#f5f5f5;box-shadow:0 3px 4px rgba(0,0,0,0.12);padding:1em 1em 0.5em 1em;margin-bottom:1em}.inline-toc .related h3{margin-top:0}.inline-toc .related li a.active{color:#000}.inline-toc .related li a:hover{background-image:linear-gradient(205deg, rgba(229,229,229,0.7) 0%,rgba(233,233,233,0.7) 20%,rgba(244,244,244,0.7) 100%)}.inline-toc #toc{display:none}.inline-toc #toc .toplevel>a{font-weight:bold;color:#000}.inline-toc #toc .toplevel>a.hastoc::after{content:'+';-webkit-box-flex:1;-webkit-flex:1;-moz-flex:1;-ms-flex:1;-o-flex:1;flex:1;text-align:right}.inline-toc #toc .toplevel.active .toc{display:block}.inline-toc #toc .toplevel.active>a.hastoc{content:"-"}.inline-toc .toc{margin:0;paddiing:0;border-top:1px solid #dbdbdb}.inline-toc .toc .toc{display:none}.inline-toc .toc .toc li{padding-left:1em;border-bottom:1px solid #dbdbdb}#cc-info{font-style:italic;font-size:0.8em;color:#848484}#cc-info .cc-logo img{width:90px;height:32px}.h1-step{display:block;font-size:0.5em;line-height:150%}.anchor-link-icon{padding-left:1px}@media only screen and (min-width: 580px){.inline-site-toc{float:left;width:175px;overflow-x:hidden}.inline-toc{width:20%;float:right;margin:0 4% 20px 4%;overflow:auto;overflow-x:hidden}.inline-toc #toc{display:block}.article-content{border-right:1px solid #f5f5f5;min-height:750px}.article-content [itemprop="articleBody"]{margin-left:195px}.cc-logo{margin:0 0 0 auto}}@media only screen and (min-width: 581px) and (max-width: 990px){.inline-toc{width:-20%}.inline-site-toc{float:left;width:175px;overflow-x:hidden}}@media only screen and (max-width: 580px){.article-content [itemprop="articleBody"]>.collapsible{height:58px;overflow:hidden}.article-content [itemprop="articleBody"]>.collapsible.active{height:auto}.article-content [itemprop="articleBody"]>.collapsible.active h2::before{content:'-'}.article-content [itemprop="articleBody"]>.collapsible h2{position:relative;margin:0;padding:15px 15px 15px 0;border-top:1px solid #dbdbdb;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.article-content [itemprop="articleBody"]>.collapsible h2::before{position:absolute;right:0;content:'+'}.article-content [itemprop="articleBody"] .related{margin:20px 0}.hidden{display:none}}.api{color:#333;font-size:14px}.api .api-summary td,.api .api-summary th{padding:5px 10px}.api .api-reference .description{margin-left:20px}.api .api-reference table .innerTable{margin:10px 0}.api .api-reference table .innerTable td,.api .api-reference table .innerTable th{padding:5px 10px;border:1px solid #eee}.api .api-reference table .innerTable th{background:none}.api .api-reference table p{margin-top:0.75em;margin-bottom:0.75em}.api .api-reference table p:first-child{margin-top:0}.api .api-reference td,.api .api-reference th{vertical-align:top;border:1px solid #eee}.api .api-reference th{background:#fafafa}.api .api-reference h2{background-color:#e8e8e8;padding:20px;margin-left:-20px;margin-right:-20px}.api .api-reference h3{margin-top:3em}.api .availability{color:#A03}.api table#intro .title{white-space:nowrap}
diff --git a/chrome/common/extensions/docs/static/sass/_html.scss b/chrome/common/extensions/docs/static/sass/_html.scss index 182a9cb4..8d20763 100644 --- a/chrome/common/extensions/docs/static/sass/_html.scss +++ b/chrome/common/extensions/docs/static/sass/_html.scss
@@ -224,7 +224,7 @@ border-bottom: 1px solid; border-top: 1px solid; overflow: hidden; - width: 85%; + max-width: 85%; padding: 1em; //border: none; //box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15), 0 0 3px rgba(0, 0, 0, 0.15);
diff --git a/chrome/common/safe_browsing/csd.proto b/chrome/common/safe_browsing/csd.proto index 4870ab3..e4e1bb27 100644 --- a/chrome/common/safe_browsing/csd.proto +++ b/chrome/common/safe_browsing/csd.proto
@@ -364,9 +364,6 @@ optional ClientDownloadRequest.SignatureInfo signature = 5; optional ClientDownloadRequest.ImageHeaders image_headers = 6; } - message OmniboxInteractionIncident { - optional string origin = 1; - } message VariationsSeedSignatureIncident { optional string variations_seed_signature = 1; } @@ -374,7 +371,7 @@ optional TrackedPreferenceIncident tracked_preference = 2; optional BinaryIntegrityIncident binary_integrity = 3; optional BlacklistLoadIncident blacklist_load = 4; - optional OmniboxInteractionIncident omnibox_interaction = 5; + // Note: skip tag 5 because it was previously used. optional VariationsSeedSignatureIncident variations_seed_signature = 6; }
diff --git a/chrome/common/url_constants.cc b/chrome/common/url_constants.cc index d021367..9db26652 100644 --- a/chrome/common/url_constants.cc +++ b/chrome/common/url_constants.cc
@@ -730,6 +730,6 @@ #endif const char kEasyUnlockLearnMoreUrl[] = - "https://support.google.com/chromebook/?p=easy_unlock"; + "https://support.google.com/chromebook/?p=smart_lock"; } // namespace chrome
diff --git a/chrome/gpu_unittests.isolate b/chrome/gpu_unittests.isolate deleted file mode 100644 index 6219888..0000000 --- a/chrome/gpu_unittests.isolate +++ /dev/null
@@ -1,20 +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. -{ - 'includes': [ - '../base/base.isolate', - ], - 'conditions': [ - ['OS=="android" or OS=="linux" or OS=="mac" or OS=="win"', { - 'variables': { - 'command': [ - '<(PRODUCT_DIR)/gpu_unittests<(EXECUTABLE_SUFFIX)', - ], - 'files': [ - '<(PRODUCT_DIR)/gpu_unittests<(EXECUTABLE_SUFFIX)', - ], - }, - }], - ], -}
diff --git a/chrome/installer/util/BUILD.gn b/chrome/installer/util/BUILD.gn index 89a0c2b..5695469 100644 --- a/chrome/installer/util/BUILD.gn +++ b/chrome/installer/util/BUILD.gn
@@ -15,6 +15,153 @@ # installer_util_nacl_win64 should be a different target with a different # name ("installer_util_minimal"?) since it's not strictly the 64-bit build # of that target. + sources = [ + "chrome_app_host_operations.cc", + "chrome_app_host_operations.h", + "chrome_binaries_operations.cc", + "chrome_binaries_operations.h", + "chrome_browser_operations.cc", + "chrome_browser_operations.h", + "chrome_browser_sxs_operations.cc", + "chrome_browser_sxs_operations.h", + "chrome_frame_operations.cc", + "chrome_frame_operations.h", + "compat_checks.cc", + "compat_checks.h", + "delete_after_reboot_helper.cc", + "delete_after_reboot_helper.h", + "eula_util.cc", + "eula_util.h", + "google_chrome_distribution.cc", + "google_chrome_distribution.h", + "html_dialog.h", + "html_dialog_impl.cc", + "installation_validator.cc", + "installation_validator.h", + "logging_installer.cc", + "logging_installer.h", + "lzma_util.cc", + "lzma_util.h", + "master_preferences.cc", + "master_preferences.h", + "product.cc", + "product.h", + "product_operations.h", + "self_cleaning_temp_dir.cc", + "self_cleaning_temp_dir.h", + "shell_util.cc", + "shell_util.h", + "uninstall_metrics.cc", + "uninstall_metrics.h", + "user_experiment.cc", + "user_experiment.h", + ] + deps += [ + ":strings", + "//base/third_party/dynamic_annotations", + "//chrome/common:constants", + "//components/metrics", + "//courgette:courgette_lib", + "//crypto", + "//third_party/bspatch", + "//third_party/icu", + "//third_party/lzma_sdk", + ] + include_dirs = [ "$root_gen_dir/installer_util_strings" ] + + # TODO(jschuh): crbug.com/167187 fix size_t to int truncations. + cflags = [ "/wd4267" ] + + # TODO(GYP) hook up corresponding version of installer_util_nacl_win64 in GN + sources += [ + "advanced_firewall_manager_win.cc", + "advanced_firewall_manager_win.h", + "app_command.cc", + "app_command.h", + "app_commands.cc", + "app_commands.h", + "app_registration_data.h", + "auto_launch_util.cc", + "auto_launch_util.h", + "browser_distribution.cc", + "browser_distribution.h", + "callback_work_item.cc", + "callback_work_item.h", + "channel_info.cc", + "channel_info.h", + "chrome_app_host_distribution.cc", + "chrome_app_host_distribution.h", + "chrome_frame_distribution.cc", + "chrome_frame_distribution.h", + "chromium_binaries_distribution.cc", + "chromium_binaries_distribution.h", + "conditional_work_item_list.cc", + "conditional_work_item_list.h", + "copy_tree_work_item.cc", + "copy_tree_work_item.h", + "create_dir_work_item.cc", + "create_dir_work_item.h", + "create_reg_key_work_item.cc", + "create_reg_key_work_item.h", + "delete_reg_key_work_item.cc", + "delete_reg_key_work_item.h", + "delete_reg_value_work_item.cc", + "delete_reg_value_work_item.h", + "delete_tree_work_item.cc", + "delete_tree_work_item.h", + "duplicate_tree_detector.cc", + "duplicate_tree_detector.h", + "firewall_manager_win.cc", + "firewall_manager_win.h", + "google_chrome_binaries_distribution.cc", + "google_chrome_binaries_distribution.h", + "google_chrome_sxs_distribution.cc", + "google_chrome_sxs_distribution.h", + "google_update_constants.cc", + "google_update_constants.h", + "google_update_experiment_util.cc", + "google_update_experiment_util.h", + "google_update_settings.cc", + "google_update_settings.h", + "google_update_util.cc", + "google_update_util.h", + "helper.cc", + "helper.h", + "install_util.cc", + "install_util.h", + "installation_state.cc", + "installation_state.h", + "installer_state.cc", + "installer_state.h", + "l10n_string_util.cc", + "l10n_string_util.h", + "language_selector.cc", + "language_selector.h", + "legacy_firewall_manager_win.cc", + "legacy_firewall_manager_win.h", + "master_preferences_constants.cc", + "master_preferences_constants.h", + "move_tree_work_item.cc", + "move_tree_work_item.h", + "non_updating_app_registration_data.cc", + "non_updating_app_registration_data.h", + "registry_key_backup.cc", + "registry_key_backup.h", + "self_reg_work_item.cc", + "self_reg_work_item.h", + "set_reg_value_work_item.cc", + "set_reg_value_work_item.h", + "updating_app_registration_data.cc", + "updating_app_registration_data.h", + "util_constants.cc", + "util_constants.h", + "wmi.cc", + "wmi.h", + "work_item.cc", + "work_item.h", + "work_item_list.cc", + "work_item_list.h", + ] } else { sources = [ "google_update_experiment_util.cc",
diff --git a/chrome/renderer/BUILD.gn b/chrome/renderer/BUILD.gn index 2ffb869..dce8efd 100644 --- a/chrome/renderer/BUILD.gn +++ b/chrome/renderer/BUILD.gn
@@ -158,7 +158,7 @@ } if (is_win) { deps += [ - #'../chrome_elf/chrome_elf.gyp:chrome_elf', TODO(GYP) + "//chrome_elf", "//third_party/wtl", ] }
diff --git a/chrome/renderer/benchmarking_extension.cc b/chrome/renderer/benchmarking_extension.cc index 555de01..1a47051 100644 --- a/chrome/renderer/benchmarking_extension.cc +++ b/chrome/renderer/benchmarking_extension.cc
@@ -119,7 +119,7 @@ static void HiResTime(const v8::FunctionCallbackInfo<v8::Value>& args) { args.GetReturnValue().Set( - static_cast<double>(base::TimeTicks::HighResNow().ToInternalValue())); + static_cast<double>(base::TimeTicks::Now().ToInternalValue())); } };
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc index c76c358..b09b820 100644 --- a/chrome/renderer/chrome_content_renderer_client.cc +++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -702,7 +702,8 @@ } #if defined(ENABLE_PLUGINS) - if (base::CommandLine::ForCurrentProcess()->HasSwitch( + if (status_value == ChromeViewHostMsg_GetPluginInfo_Status::kAllowed && + base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnablePluginPowerSaver)) { status_value = ChromeViewHostMsg_GetPluginInfo_Status::kPlayImportantContent;
diff --git a/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc b/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc index 8625523..4fe2ff4 100644 --- a/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc +++ b/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc
@@ -16,12 +16,12 @@ #include "chrome/renderer/extensions/app_bindings.h" #include "chrome/renderer/extensions/automation_internal_custom_bindings.h" #include "chrome/renderer/extensions/chrome_v8_context.h" -#include "chrome/renderer/extensions/enterprise_platform_keys_natives.h" #include "chrome/renderer/extensions/file_browser_handler_custom_bindings.h" #include "chrome/renderer/extensions/file_manager_private_custom_bindings.h" #include "chrome/renderer/extensions/media_galleries_custom_bindings.h" #include "chrome/renderer/extensions/notifications_native_handler.h" #include "chrome/renderer/extensions/page_capture_custom_bindings.h" +#include "chrome/renderer/extensions/platform_keys_natives.h" #include "chrome/renderer/extensions/sync_file_system_custom_bindings.h" #include "chrome/renderer/extensions/tab_finder.h" #include "chrome/renderer/extensions/tabs_custom_bindings.h" @@ -100,10 +100,6 @@ scoped_ptr<NativeHandler>( new extensions::SyncFileSystemCustomBindings(context))); module_system->RegisterNativeHandler( - "enterprise_platform_keys_natives", - scoped_ptr<NativeHandler>( - new extensions::EnterprisePlatformKeysNatives(context))); - module_system->RegisterNativeHandler( "file_browser_handler", scoped_ptr<NativeHandler>( new extensions::FileBrowserHandlerCustomBindings(context))); @@ -124,6 +120,9 @@ scoped_ptr<NativeHandler>( new extensions::PageCaptureCustomBindings(context))); module_system->RegisterNativeHandler( + "platform_keys_natives", + scoped_ptr<NativeHandler>(new extensions::PlatformKeysNatives(context))); + module_system->RegisterNativeHandler( "tabs", scoped_ptr<NativeHandler>(new extensions::TabsCustomBindings(context))); module_system->RegisterNativeHandler( @@ -161,16 +160,12 @@ IDR_ENTERPRISE_PLATFORM_KEYS_CUSTOM_BINDINGS_JS); source_map->RegisterSource("enterprise.platformKeys.internalAPI", IDR_ENTERPRISE_PLATFORM_KEYS_INTERNAL_API_JS); - source_map->RegisterSource("enterprise.platformKeys.Key", - IDR_ENTERPRISE_PLATFORM_KEYS_KEY_JS); source_map->RegisterSource("enterprise.platformKeys.KeyPair", IDR_ENTERPRISE_PLATFORM_KEYS_KEY_PAIR_JS); source_map->RegisterSource("enterprise.platformKeys.SubtleCrypto", IDR_ENTERPRISE_PLATFORM_KEYS_SUBTLE_CRYPTO_JS); source_map->RegisterSource("enterprise.platformKeys.Token", IDR_ENTERPRISE_PLATFORM_KEYS_TOKEN_JS); - source_map->RegisterSource("enterprise.platformKeys.utils", - IDR_ENTERPRISE_PLATFORM_KEYS_UTILS_JS); source_map->RegisterSource("feedbackPrivate", IDR_FEEDBACK_PRIVATE_CUSTOM_BINDINGS_JS); source_map->RegisterSource("fileBrowserHandler", @@ -194,6 +189,12 @@ source_map->RegisterSource("pageAction", IDR_PAGE_ACTION_CUSTOM_BINDINGS_JS); source_map->RegisterSource("pageCapture", IDR_PAGE_CAPTURE_CUSTOM_BINDINGS_JS); + source_map->RegisterSource("platformKeys.internalAPI", + IDR_PLATFORM_KEYS_INTERNAL_API_JS); + source_map->RegisterSource("platformKeys.Key", IDR_PLATFORM_KEYS_KEY_JS); + source_map->RegisterSource("platformKeys.SubtleCrypto", + IDR_PLATFORM_KEYS_SUBTLE_CRYPTO_JS); + source_map->RegisterSource("platformKeys.utils", IDR_PLATFORM_KEYS_UTILS_JS); source_map->RegisterSource("syncFileSystem", IDR_SYNC_FILE_SYSTEM_CUSTOM_BINDINGS_JS); source_map->RegisterSource("systemIndicator",
diff --git a/chrome/renderer/extensions/enterprise_platform_keys_natives.cc b/chrome/renderer/extensions/platform_keys_natives.cc similarity index 92% rename from chrome/renderer/extensions/enterprise_platform_keys_natives.cc rename to chrome/renderer/extensions/platform_keys_natives.cc index 9f84f7c6..779b909 100644 --- a/chrome/renderer/extensions/enterprise_platform_keys_natives.cc +++ b/chrome/renderer/extensions/platform_keys_natives.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 "chrome/renderer/extensions/enterprise_platform_keys_natives.h" +#include "chrome/renderer/extensions/platform_keys_natives.h" #include <string> @@ -73,15 +73,14 @@ } // namespace -EnterprisePlatformKeysNatives::EnterprisePlatformKeysNatives( - ScriptContext* context) +PlatformKeysNatives::PlatformKeysNatives(ScriptContext* context) : ObjectBackedNativeHandler(context) { RouteFunction("NormalizeAlgorithm", - base::Bind(&EnterprisePlatformKeysNatives::NormalizeAlgorithm, + base::Bind(&PlatformKeysNatives::NormalizeAlgorithm, base::Unretained(this))); } -void EnterprisePlatformKeysNatives::NormalizeAlgorithm( +void PlatformKeysNatives::NormalizeAlgorithm( const v8::FunctionCallbackInfo<v8::Value>& call_info) { DCHECK_EQ(call_info.Length(), 2); DCHECK(call_info[0]->IsObject());
diff --git a/chrome/renderer/extensions/enterprise_platform_keys_natives.h b/chrome/renderer/extensions/platform_keys_natives.h similarity index 71% rename from chrome/renderer/extensions/enterprise_platform_keys_natives.h rename to chrome/renderer/extensions/platform_keys_natives.h index 9649aee..e833414 100644 --- a/chrome/renderer/extensions/enterprise_platform_keys_natives.h +++ b/chrome/renderer/extensions/platform_keys_natives.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 CHROME_RENDERER_EXTENSIONS_ENTERPRISE_PLATFORM_KEYS_NATIVES_H_ -#define CHROME_RENDERER_EXTENSIONS_ENTERPRISE_PLATFORM_KEYS_NATIVES_H_ +#ifndef CHROME_RENDERER_EXTENSIONS_PLATFORM_KEYS_NATIVES_H_ +#define CHROME_RENDERER_EXTENSIONS_PLATFORM_KEYS_NATIVES_H_ #include "extensions/renderer/object_backed_native_handler.h" #include "v8/include/v8.h" @@ -11,9 +11,9 @@ namespace extensions { class ScriptContext; -class EnterprisePlatformKeysNatives : public ObjectBackedNativeHandler { +class PlatformKeysNatives : public ObjectBackedNativeHandler { public: - explicit EnterprisePlatformKeysNatives(ScriptContext* context); + explicit PlatformKeysNatives(ScriptContext* context); private: // Normalizes algorithm parameters, and then validates the expected parameters @@ -27,9 +27,9 @@ // arrays instead of typed arrays (e.g. for RSA publicExponent). void NormalizeAlgorithm(const v8::FunctionCallbackInfo<v8::Value>& call_info); - DISALLOW_COPY_AND_ASSIGN(EnterprisePlatformKeysNatives); + DISALLOW_COPY_AND_ASSIGN(PlatformKeysNatives); }; } // namespace extensions -#endif // CHROME_RENDERER_EXTENSIONS_ENTERPRISE_PLATFORM_KEYS_NATIVES_H_ +#endif // CHROME_RENDERER_EXTENSIONS_PLATFORM_KEYS_NATIVES_H_
diff --git a/chrome/renderer/plugins/chrome_plugin_placeholder.cc b/chrome/renderer/plugins/chrome_plugin_placeholder.cc index 46a56ce..7be0698 100644 --- a/chrome/renderer/plugins/chrome_plugin_placeholder.cc +++ b/chrome/renderer/plugins/chrome_plugin_placeholder.cc
@@ -303,7 +303,8 @@ case chrome::MENU_COMMAND_PLUGIN_RUN: { RenderThread::Get()->RecordAction(UserMetricsAction("Plugin_Load_Menu")); #if defined(ENABLE_PLUGINS) - DisablePowerSaverForInstance(); + DisablePowerSaverForInstance( + content::PluginInstanceThrottler::UNTHROTTLE_METHOD_BY_CLICK); #endif LoadPlugin(); break;
diff --git a/chrome/renderer/printing/chrome_print_web_view_helper_delegate.cc b/chrome/renderer/printing/chrome_print_web_view_helper_delegate.cc index 6eb3881..576bb15 100644 --- a/chrome/renderer/printing/chrome_print_web_view_helper_delegate.cc +++ b/chrome/renderer/printing/chrome_print_web_view_helper_delegate.cc
@@ -4,10 +4,13 @@ #include "chrome/renderer/printing/chrome_print_web_view_helper_delegate.h" +#include <vector> + #include "base/command_line.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/render_messages.h" #include "chrome/renderer/prerender/prerender_helper.h" +#include "content/public/renderer/render_frame.h" #include "content/public/renderer/render_view.h" #include "ipc/ipc_message.h" #include "third_party/WebKit/public/web/WebDocument.h" @@ -17,6 +20,7 @@ #if defined(ENABLE_EXTENSIONS) #include "chrome/common/extensions/extension_constants.h" #include "extensions/common/constants.h" +#include "extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container.h" #endif // defined(ENABLE_EXTENSIONS) ChromePrintWebViewHelperDelegate::~ChromePrintWebViewHelperDelegate(){ @@ -59,3 +63,26 @@ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); return !command_line->HasSwitch(switches::kDisablePrintPreview); } + +bool ChromePrintWebViewHelperDelegate::OverridePrint( + blink::WebLocalFrame* frame) { +#if defined(ENABLE_EXTENSIONS) + if (!frame->document().isPluginDocument()) + return false; + + std::vector<extensions::MimeHandlerViewContainer*> mime_handlers = + extensions::MimeHandlerViewContainer::FromRenderFrame( + content::RenderFrame::FromWebFrame(frame)); + if (!mime_handlers.empty()) { + // This message is handled in chrome/browser/resources/pdf/pdf.js and + // instructs the PDF plugin to print. This is to make window.print() on a + // PDF plugin document correctly print the PDF. See + // https://crbug.com/448720. + base::DictionaryValue message; + message.SetString("type", "print"); + mime_handlers.front()->PostMessageFromValue(message); + return true; + } +#endif // defined(ENABLE_EXTENSIONS) + return false; +}
diff --git a/chrome/renderer/printing/chrome_print_web_view_helper_delegate.h b/chrome/renderer/printing/chrome_print_web_view_helper_delegate.h index 33f78d4..d290b56 100644 --- a/chrome/renderer/printing/chrome_print_web_view_helper_delegate.h +++ b/chrome/renderer/printing/chrome_print_web_view_helper_delegate.h
@@ -21,6 +21,7 @@ bool IsPrintPreviewEnabled() override; + bool OverridePrint(blink::WebLocalFrame* frame) override; }; // class ChromePrintWebViewHelperDelegate #endif // CHROME_RENDERER_PRINTING_CHROME_PRINT_WEB_VIEW_HELPER_DELEGATE_H_
diff --git a/chrome/renderer/resources/extensions/enterprise_platform_keys/key_pair.js b/chrome/renderer/resources/extensions/enterprise_platform_keys/key_pair.js index 581a2e87..dc06f16 100644 --- a/chrome/renderer/resources/extensions/enterprise_platform_keys/key_pair.js +++ b/chrome/renderer/resources/extensions/enterprise_platform_keys/key_pair.js
@@ -3,8 +3,8 @@ // found in the LICENSE file. var utils = require('utils'); -var intersect = require('enterprise.platformKeys.utils').intersect; -var keyModule = require('enterprise.platformKeys.Key'); +var intersect = require('platformKeys.utils').intersect; +var keyModule = require('platformKeys.Key'); var Key = keyModule.Key; var KeyType = keyModule.KeyType; var KeyUsage = keyModule.KeyUsage;
diff --git a/chrome/renderer/resources/extensions/enterprise_platform_keys/subtle_crypto.js b/chrome/renderer/resources/extensions/enterprise_platform_keys/subtle_crypto.js index 017a3e26..ece24305 100644 --- a/chrome/renderer/resources/extensions/enterprise_platform_keys/subtle_crypto.js +++ b/chrome/renderer/resources/extensions/enterprise_platform_keys/subtle_crypto.js
@@ -4,14 +4,15 @@ var utils = require('utils'); var internalAPI = require('enterprise.platformKeys.internalAPI'); -var intersect = require('enterprise.platformKeys.utils').intersect; +var intersect = require('platformKeys.utils').intersect; +var subtleCryptoModule = require('platformKeys.SubtleCrypto'); +var SubtleCrypto = subtleCryptoModule.SubtleCrypto; +var SubtleCryptoImpl = subtleCryptoModule.SubtleCryptoImpl; var KeyPair = require('enterprise.platformKeys.KeyPair').KeyPair; -var keyModule = require('enterprise.platformKeys.Key'); -var getSpki = keyModule.getSpki; -var KeyUsage = keyModule.KeyUsage; +var KeyUsage = require('platformKeys.Key').KeyUsage; var normalizeAlgorithm = - requireNative('enterprise_platform_keys_natives').NormalizeAlgorithm; + requireNative('platform_keys_natives').NormalizeAlgorithm; // This error is thrown by the internal and public API's token functions and // must be rethrown by this custom binding. Keep this in sync with the C++ part @@ -72,14 +73,18 @@ /** * Implementation of WebCrypto.SubtleCrypto used in enterprise.platformKeys. + * Derived from platformKeys.SubtleCrypto. * @param {string} tokenId The id of the backing Token. * @constructor */ -var SubtleCryptoImpl = function(tokenId) { - this.tokenId = tokenId; +var EnterpriseSubtleCryptoImpl = function(tokenId) { + SubtleCryptoImpl.call(this, tokenId); }; -SubtleCryptoImpl.prototype.generateKey = +EnterpriseSubtleCryptoImpl.prototype = + Object.create(SubtleCryptoImpl.prototype); + +EnterpriseSubtleCryptoImpl.prototype.generateKey = function(algorithm, extractable, keyUsages) { var subtleCrypto = this; return new Promise(function(resolve, reject) { @@ -128,58 +133,11 @@ }); }; -SubtleCryptoImpl.prototype.sign = function(algorithm, key, dataView) { - var subtleCrypto = this; - return new Promise(function(resolve, reject) { - if (key.type != 'private' || key.usages.indexOf(KeyUsage.sign) == -1) - throw CreateInvalidAccessError(); - - var normalizedAlgorithmParameters = - normalizeAlgorithm(algorithm, 'Sign'); - if (!normalizedAlgorithmParameters) { - // TODO(pneubeck): It's not clear from the WebCrypto spec which error to - // throw here. - throw CreateSyntaxError(); - } - - // Create an ArrayBuffer that equals the dataView. Note that dataView.buffer - // might contain more data than dataView. - var data = dataView.buffer.slice(dataView.byteOffset, - dataView.byteOffset + dataView.byteLength); - internalAPI.sign(subtleCrypto.tokenId, - getSpki(key), - key.algorithm.hash.name, - data, - function(signature) { - if (catchInvalidTokenError(reject)) - return; - if (chrome.runtime.lastError) { - reject(CreateOperationError()); - return; - } - resolve(signature); - }); - }); -}; - -SubtleCryptoImpl.prototype.exportKey = function(format, key) { - return new Promise(function(resolve, reject) { - if (format == 'pkcs8') { - // Either key.type is not 'private' or the key is not extractable. In both - // cases the error is the same. - throw CreateInvalidAccessError(); - } else if (format == 'spki') { - if (key.type != 'public') - throw CreateInvalidAccessError(); - resolve(getSpki(key)); - } else { - // TODO(pneubeck): It should be possible to export to format 'jwk'. - throw CreateNotSupportedError(); - } - }); -}; - exports.SubtleCrypto = utils.expose('SubtleCrypto', - SubtleCryptoImpl, - {functions:['generateKey', 'sign', 'exportKey']}); + EnterpriseSubtleCryptoImpl, + { + superclass: SubtleCrypto, + functions: ['generateKey'] + // ['sign', 'exportKey'] are exposed by the base class + });
diff --git a/chrome/renderer/resources/extensions/extension_options.js b/chrome/renderer/resources/extensions/extension_options.js index cc377e11..1b8fa78 100644 --- a/chrome/renderer/resources/extensions/extension_options.js +++ b/chrome/renderer/resources/extensions/extension_options.js
@@ -37,7 +37,6 @@ this.autosizeDeferred = false; this.setupElementProperties(); - this.parseExtensionAttribute(); }; ExtensionOptionsImpl.prototype.__proto__ = GuestViewContainer.prototype; @@ -56,17 +55,17 @@ } ExtensionOptionsImpl.prototype.onElementAttached = function() { - this.parseExtensionAttribute(); this.createGuest(); } -ExtensionOptionsImpl.prototype.buildAttachParams = function() { +ExtensionOptionsImpl.prototype.buildContainerParams = function() { var params = { 'autosize': this.element.hasAttribute('autosize'), 'maxheight': parseInt(this.maxheight || 0), 'maxwidth': parseInt(this.maxwidth || 0), 'minheight': parseInt(this.minheight || 0), - 'minwidth': parseInt(this.minwidth || 0) + 'minwidth': parseInt(this.minwidth || 0), + 'extensionId': this.element.getAttribute('extension') }; return params; }; @@ -75,15 +74,14 @@ if (!this.elementAttached) { return; } - var params = { - 'extensionId': this.extensionId, - }; - this.guest.create(params, function() { + // Destroy the old guest if one exists. + this.guest.destroy(); + + this.guest.create(this.buildParams(), function() { if (!this.guest.getId()) { // Fire a createfailed event here rather than in ExtensionOptionsGuest // because the guest will not be created, and cannot fire an event. - this.initCalled = false; var createFailedEvent = new Event('createfailed', { bubbles: true }); this.dispatchEvent(createFailedEvent); } else { @@ -107,20 +105,8 @@ if (oldValue === newValue) return; - if (name == 'extension' && !oldValue && !!newValue) { - this.extensionId = newValue; - // If the browser plugin is not ready then don't create the guest until - // it is ready (in handleBrowserPluginAttributeMutation). - if (!this.internalInstanceId) - return; - - // If a guest view does not exist then create one. - if (!this.guest.getId()) { - this.createGuest(); - return; - } - // TODO(ericzeng): Implement navigation to another guest view if we want - // that functionality. + if (name == 'extension') { + this.createGuest(); } else if (AUTO_SIZE_ATTRIBUTES.hasOwnProperty(name) > -1) { this[name] = newValue; this.resetSizeConstraintsIfInvalid(); @@ -128,7 +114,7 @@ if (!this.guest.getId()) return; - this.guest.setAutoSize({ + this.guest.setSize({ 'enableAutoSize': this.element.hasAttribute('autosize'), 'min': { 'width': parseInt(this.minwidth || 0), @@ -156,14 +142,6 @@ } }; -ExtensionOptionsImpl.prototype.parseExtensionAttribute = function() { - if (this.element.hasAttribute('extension')) { - this.extensionId = this.element.getAttribute('extension'); - return true; - } - return false; -}; - ExtensionOptionsImpl.prototype.resize = function(newWidth, newHeight, oldWidth, oldHeight) { this.element.style.width = newWidth + 'px'; @@ -177,7 +155,7 @@ if (newHeight > this.minheight) this.minheight = newHeight; - this.guest.setAutoSize({ + this.guest.setSize({ 'enableAutoSize': this.element.hasAttribute('autosize'), 'min': { 'width': parseInt(this.minwidth || 0), @@ -237,7 +215,7 @@ Object.defineProperty(this.element, 'extension', { get: function() { - return this.extensionId; + return this.element.getAttribute('extension'); }.bind(this), set: function(value) { this.element.setAttribute('extension', value);
diff --git a/chrome/renderer/resources/extensions/platform_keys/OWNERS b/chrome/renderer/resources/extensions/platform_keys/OWNERS new file mode 100644 index 0000000..713045b6 --- /dev/null +++ b/chrome/renderer/resources/extensions/platform_keys/OWNERS
@@ -0,0 +1 @@ +pneubeck@chromium.org
diff --git a/chrome/renderer/resources/extensions/platform_keys/internal_api.js b/chrome/renderer/resources/extensions/platform_keys/internal_api.js new file mode 100644 index 0000000..b152116 --- /dev/null +++ b/chrome/renderer/resources/extensions/platform_keys/internal_api.js
@@ -0,0 +1,9 @@ +// Copyright 2015 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. + +var binding = require('binding') + .Binding.create('platformKeysInternal') + .generate(); + +exports.sign = binding.sign;
diff --git a/chrome/renderer/resources/extensions/enterprise_platform_keys/key.js b/chrome/renderer/resources/extensions/platform_keys/key.js similarity index 100% rename from chrome/renderer/resources/extensions/enterprise_platform_keys/key.js rename to chrome/renderer/resources/extensions/platform_keys/key.js
diff --git a/chrome/renderer/resources/extensions/platform_keys/subtle_crypto.js b/chrome/renderer/resources/extensions/platform_keys/subtle_crypto.js new file mode 100644 index 0000000..14a5388 --- /dev/null +++ b/chrome/renderer/resources/extensions/platform_keys/subtle_crypto.js
@@ -0,0 +1,119 @@ +// Copyright 2015 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. + +var utils = require('utils'); +var internalAPI = require('platformKeys.internalAPI'); +var keyModule = require('platformKeys.Key'); +var getSpki = keyModule.getSpki; +var KeyUsage = keyModule.KeyUsage; + +var normalizeAlgorithm = + requireNative('platform_keys_natives').NormalizeAlgorithm; + +// This error is thrown by the internal and public API's token functions and +// must be rethrown by this custom binding. Keep this in sync with the C++ part +// of this API. +var errorInvalidToken = "The token is not valid."; + +// The following errors are specified in WebCrypto. +// TODO(pneubeck): These should be DOMExceptions. +function CreateNotSupportedError() { + return new Error('The algorithm is not supported'); +} + +function CreateInvalidAccessError() { + return new Error('The requested operation is not valid for the provided key'); +} + +function CreateDataError() { + return new Error('Data provided to an operation does not meet requirements'); +} + +function CreateSyntaxError() { + return new Error('A required parameter was missing or out-of-range'); +} + +function CreateOperationError() { + return new Error('The operation failed for an operation-specific reason'); +} + +// Catches an |internalErrorInvalidToken|. If so, forwards it to |reject| and +// returns true. +function catchInvalidTokenError(reject) { + if (chrome.runtime.lastError && + chrome.runtime.lastError.message == errorInvalidToken) { + reject(chrome.runtime.lastError); + return true; + } + return false; +} + +/** + * Implementation of WebCrypto.SubtleCrypto used in platformKeys and + * enterprise.platformKeys. + * @param {string} tokenId The id of the backing Token. + * @constructor + */ +var SubtleCryptoImpl = function(tokenId) { + this.tokenId = tokenId; +}; + +SubtleCryptoImpl.prototype.sign = function(algorithm, key, dataView) { + var subtleCrypto = this; + return new Promise(function(resolve, reject) { + if (key.type != 'private' || key.usages.indexOf(KeyUsage.sign) == -1) + throw CreateInvalidAccessError(); + + var normalizedAlgorithmParameters = + normalizeAlgorithm(algorithm, 'Sign'); + if (!normalizedAlgorithmParameters) { + // TODO(pneubeck): It's not clear from the WebCrypto spec which error to + // throw here. + throw CreateSyntaxError(); + } + + // Create an ArrayBuffer that equals the dataView. Note that dataView.buffer + // might contain more data than dataView. + var data = dataView.buffer.slice(dataView.byteOffset, + dataView.byteOffset + dataView.byteLength); + internalAPI.sign(subtleCrypto.tokenId, + getSpki(key), + key.algorithm.hash.name, + data, + function(signature) { + if (catchInvalidTokenError(reject)) + return; + if (chrome.runtime.lastError) { + reject(CreateOperationError()); + return; + } + resolve(signature); + }); + }); +}; + +SubtleCryptoImpl.prototype.exportKey = function(format, key) { + return new Promise(function(resolve, reject) { + if (format == 'pkcs8') { + // Either key.type is not 'private' or the key is not extractable. In both + // cases the error is the same. + throw CreateInvalidAccessError(); + } else if (format == 'spki') { + if (key.type != 'public') + throw CreateInvalidAccessError(); + resolve(getSpki(key)); + } else { + // TODO(pneubeck): It should be possible to export to format 'jwk'. + throw CreateNotSupportedError(); + } + }); +}; + +// Required for subclassing. +exports.SubtleCryptoImpl = SubtleCryptoImpl + +exports.SubtleCrypto = + utils.expose('SubtleCrypto', + SubtleCryptoImpl, + {functions:['sign', 'exportKey']});
diff --git a/chrome/renderer/resources/extensions/enterprise_platform_keys/utils.js b/chrome/renderer/resources/extensions/platform_keys/utils.js similarity index 100% rename from chrome/renderer/resources/extensions/enterprise_platform_keys/utils.js rename to chrome/renderer/resources/extensions/platform_keys/utils.js
diff --git a/chrome/renderer/resources/renderer_resources.grd b/chrome/renderer/resources/renderer_resources.grd index 7fdc682..da0a535 100644 --- a/chrome/renderer/resources/renderer_resources.grd +++ b/chrome/renderer/resources/renderer_resources.grd
@@ -53,11 +53,9 @@ <include name="IDR_DOWNLOADS_CUSTOM_BINDINGS_JS" file="extensions\downloads_custom_bindings.js" type="BINDATA" /> <include name="IDR_ENTERPRISE_PLATFORM_KEYS_CUSTOM_BINDINGS_JS" file="extensions\enterprise_platform_keys_custom_bindings.js" type="BINDATA" /> <include name="IDR_ENTERPRISE_PLATFORM_KEYS_INTERNAL_API_JS" file="extensions\enterprise_platform_keys\internal_api.js" type="BINDATA" /> - <include name="IDR_ENTERPRISE_PLATFORM_KEYS_KEY_JS" file="extensions\enterprise_platform_keys\key.js" type="BINDATA" /> <include name="IDR_ENTERPRISE_PLATFORM_KEYS_KEY_PAIR_JS" file="extensions\enterprise_platform_keys\key_pair.js" type="BINDATA" /> <include name="IDR_ENTERPRISE_PLATFORM_KEYS_SUBTLE_CRYPTO_JS" file="extensions\enterprise_platform_keys\subtle_crypto.js" type="BINDATA" /> <include name="IDR_ENTERPRISE_PLATFORM_KEYS_TOKEN_JS" file="extensions\enterprise_platform_keys\token.js" type="BINDATA" /> - <include name="IDR_ENTERPRISE_PLATFORM_KEYS_UTILS_JS" file="extensions\enterprise_platform_keys\utils.js" type="BINDATA" /> <include name="IDR_EXTENSION_OPTIONS_JS" file="extensions\extension_options.js" type="BINDATA"/> <include name="IDR_EXTENSION_OPTIONS_EVENTS_JS" file="extensions\extension_options_events.js" type="BINDATA"/> <include name="IDR_FEEDBACK_PRIVATE_CUSTOM_BINDINGS_JS" file="extensions\feedback_private_custom_bindings.js" type="BINDATA" /> @@ -76,6 +74,10 @@ <include name="IDR_OMNIBOX_CUSTOM_BINDINGS_JS" file="extensions\omnibox_custom_bindings.js" type="BINDATA" /> <include name="IDR_PAGE_ACTION_CUSTOM_BINDINGS_JS" file="extensions\page_action_custom_bindings.js" type="BINDATA" /> <include name="IDR_PAGE_CAPTURE_CUSTOM_BINDINGS_JS" file="extensions\page_capture_custom_bindings.js" type="BINDATA" /> + <include name="IDR_PLATFORM_KEYS_INTERNAL_API_JS" file="extensions\platform_keys\internal_api.js" type="BINDATA" /> + <include name="IDR_PLATFORM_KEYS_KEY_JS" file="extensions\platform_keys\key.js" type="BINDATA" /> + <include name="IDR_PLATFORM_KEYS_SUBTLE_CRYPTO_JS" file="extensions\platform_keys\subtle_crypto.js" type="BINDATA" /> + <include name="IDR_PLATFORM_KEYS_UTILS_JS" file="extensions\platform_keys\utils.js" type="BINDATA" /> <include name="IDR_SYNC_FILE_SYSTEM_CUSTOM_BINDINGS_JS" file="extensions\sync_file_system_custom_bindings.js" type="BINDATA" /> <include name="IDR_SYSTEM_INDICATOR_CUSTOM_BINDINGS_JS" file="extensions\system_indicator_custom_bindings.js" type="BINDATA" /> <include name="IDR_TAB_CAPTURE_CUSTOM_BINDINGS_JS" file="extensions\tab_capture_custom_bindings.js" type="BINDATA" />
diff --git a/chrome/service/cloud_print/cloud_print_proxy.cc b/chrome/service/cloud_print/cloud_print_proxy.cc index ae56186..a98fecb4 100644 --- a/chrome/service/cloud_print/cloud_print_proxy.cc +++ b/chrome/service/cloud_print/cloud_print_proxy.cc
@@ -45,7 +45,7 @@ #if defined(OS_POSIX) && !defined(OS_MACOSX) base::Process process = base::LaunchProcess(cmd_line, base::LaunchOptions()); if (process.IsValid()) - base::EnsureProcessGetsReaped(process.pid()); + base::EnsureProcessGetsReaped(process.Pid()); #else base::LaunchOptions launch_options; #if defined(OS_WIN)
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 1139790..e2f3c38 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -95,7 +95,6 @@ "//chrome/common:test_support", "//chrome/renderer:test_support", "//components/bookmarks/test", - "//components/component_updater:test_support", "//components/gcm_driver:test_support", "//components/history/core/test:test", "//components/metrics:test_support", @@ -106,6 +105,7 @@ "//components/search_engines:test_support", "//components/signin/core/browser:test_support", "//components/sync_driver:test_support", + "//components/update_client:test_support", "//content/public/app:both", "//ui/gfx:test_support", "//net", @@ -157,9 +157,7 @@ deps += [ "//crypto:platform" ] } if (is_win) { - deps += [ - "//third_party/wtl", - ] + deps += [ "//third_party/wtl" ] if (use_aura) { deps += [ "//win8:test_registrar_constants",
diff --git a/chrome/test/DEPS b/chrome/test/DEPS index 2e14c50a..88bbd0e01 100644 --- a/chrome/test/DEPS +++ b/chrome/test/DEPS
@@ -18,7 +18,7 @@ "+gin/public", "+grit", # For generated headers. TODO(thestig): Remove. "+media/base", - "+mojo/edk/embedder", "+sandbox/win/tests", + "+third_party/mojo/src/mojo/edk/embedder", "+win8/test", ]
diff --git a/chrome/test/base/run_all_unittests.cc b/chrome/test/base/run_all_unittests.cc index 639bcff..3ab966f 100644 --- a/chrome/test/base/run_all_unittests.cc +++ b/chrome/test/base/run_all_unittests.cc
@@ -6,7 +6,7 @@ #include "base/test/launcher/unit_test_launcher.h" #include "chrome/test/base/chrome_unit_test_suite.h" #include "content/public/test/unittest_test_suite.h" -#include "mojo/edk/embedder/test_embedder.h" +#include "third_party/mojo/src/mojo/edk/embedder/test_embedder.h" int main(int argc, char **argv) { content::UnitTestTestSuite test_suite(new ChromeUnitTestSuite(argc, argv));
diff --git a/chrome/test/base/testing_browser_process_platform_part.h b/chrome/test/base/testing_browser_process_platform_part.h index d53b442..8fd9869 100644 --- a/chrome/test/base/testing_browser_process_platform_part.h +++ b/chrome/test/base/testing_browser_process_platform_part.h
@@ -17,7 +17,7 @@ #if defined(OS_CHROMEOS) // Overridden from BrowserProcessPlatformPart: - virtual chromeos::OomPriorityManager* oom_priority_manager() override; + chromeos::OomPriorityManager* oom_priority_manager() override; #endif private:
diff --git a/chrome/test/base/testing_profile.h b/chrome/test/base/testing_profile.h index edb28de..fc95195 100644 --- a/chrome/test/base/testing_profile.h +++ b/chrome/test/base/testing_profile.h
@@ -310,13 +310,9 @@ void SetExitType(ExitType exit_type) override {} ExitType GetLastSessionExitType() override; #if defined(OS_CHROMEOS) - virtual void ChangeAppLocale(const std::string&, - AppLocaleChangedVia) override { - } - virtual void OnLogin() override { - } - virtual void InitChromeOSPreferences() override { - } + void ChangeAppLocale(const std::string&, AppLocaleChangedVia) override {} + void OnLogin() override {} + void InitChromeOSPreferences() override {} #endif // defined(OS_CHROMEOS) PrefProxyConfigTracker* GetProxyConfigTracker() override;
diff --git a/chrome/test/base/testing_profile_manager.cc b/chrome/test/base/testing_profile_manager.cc index 63295182..064a681 100644 --- a/chrome/test/base/testing_profile_manager.cc +++ b/chrome/test/base/testing_profile_manager.cc
@@ -18,6 +18,7 @@ #endif const char kGuestProfileName[] = "Guest"; +const char kSystemProfileName[] = "System"; namespace testing { @@ -136,6 +137,24 @@ return profile; } +TestingProfile* TestingProfileManager::CreateSystemProfile() { + DCHECK(called_set_up_); + + // Create the profile and register it. + TestingProfile::Builder builder; + builder.SetPath(ProfileManager::GetSystemProfilePath()); + + // Add the system profile to the profile manager, but not to the info cache. + TestingProfile* profile = builder.Build().release(); + profile->set_profile_name(kSystemProfileName); + + profile_manager_->AddProfile(profile); // Takes ownership. + + testing_profiles_.insert(std::make_pair(kSystemProfileName, profile)); + + return profile; +} + void TestingProfileManager::DeleteTestingProfile(const std::string& name) { DCHECK(called_set_up_); @@ -170,6 +189,16 @@ profile_manager_->profiles_info_.erase(ProfileManager::GetGuestProfilePath()); } +void TestingProfileManager::DeleteSystemProfile() { + DCHECK(called_set_up_); + + TestingProfilesMap::iterator it = testing_profiles_.find(kSystemProfileName); + DCHECK(it != testing_profiles_.end()); + + profile_manager_->profiles_info_.erase( + ProfileManager::GetSystemProfilePath()); +} + void TestingProfileManager::DeleteProfileInfoCache() { profile_manager_->profile_info_cache_.reset(NULL); }
diff --git a/chrome/test/base/testing_profile_manager.h b/chrome/test/base/testing_profile_manager.h index 52f357f..e051379 100644 --- a/chrome/test/base/testing_profile_manager.h +++ b/chrome/test/base/testing_profile_manager.h
@@ -67,6 +67,13 @@ // The subsystem owns the Profile and returns a weak pointer. TestingProfile* CreateGuestProfile(); + // Creates a new system TestingProfile whose data lives in the system profile + // test environment directory, as specified by the profile manager. + // This profile will not be added to the ProfileInfoCache. This will + // register the TestingProfile with the profile subsystem as well. + // The subsystem owns the Profile and returns a weak pointer. + TestingProfile* CreateSystemProfile(); + // Deletes a TestingProfile from the profile subsystem. void DeleteTestingProfile(const std::string& profile_name); @@ -77,6 +84,9 @@ // Deletes a guest TestingProfile from the profile manager. void DeleteGuestProfile(); + // Deletes a system TestingProfile from the profile manager. + void DeleteSystemProfile(); + // Deletes the cache instance. This is useful for testing that the cache is // properly persisting data. void DeleteProfileInfoCache();
diff --git a/chrome/test/base/view_event_test_platform_part_chromeos.cc b/chrome/test/base/view_event_test_platform_part_chromeos.cc index 4e9b12e9..7d32b88 100644 --- a/chrome/test/base/view_event_test_platform_part_chromeos.cc +++ b/chrome/test/base/view_event_test_platform_part_chromeos.cc
@@ -23,10 +23,10 @@ public: explicit ViewEventTestPlatformPartChromeOS( ui::ContextFactory* context_factory); - virtual ~ViewEventTestPlatformPartChromeOS(); + ~ViewEventTestPlatformPartChromeOS() override; // Overridden from ViewEventTestPlatformPart: - virtual gfx::NativeWindow GetContext() override { + gfx::NativeWindow GetContext() override { return ash::Shell::GetPrimaryRootWindow(); }
diff --git a/chrome/test/chromedriver/chrome/mobile_device_list.cc b/chrome/test/chromedriver/chrome/mobile_device_list.cc index dc51e17..3c31b0f 100644 --- a/chrome/test/chromedriver/chrome/mobile_device_list.cc +++ b/chrome/test/chromedriver/chrome/mobile_device_list.cc
@@ -1,181 +1,196 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. +// Copyright 2015 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. +// This file was generated at (2015-01-22 12:13:16.600114) by running: +// chrome/test/chromedriver/embed_mobile_devices_in_cpp.py --directory +// chrome/test/chromedriver/chrome/ +// third_party/WebKit/Source/devtools/front_end/toolbox/OverridesUI.js + #include "chrome/test/chromedriver/chrome/mobile_device_list.h" const char kMobileDevices[] = - "[{\"title\": \"Apple iPhone 3GS\", \"width\": 320, \"height\": 480, \"dev" - "iceScaleFactor\": 1, \"userAgent\": \"Mozilla/5.0 (iPhone; U; CPU iPhone " - "OS 4_2_1 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) V" - "ersion/5.0.2 Mobile/8C148 Safari/6533.18.5\", \"touch\": true, \"mobile\"" - ": true},{\"title\": \"Apple iPhone 4\", \"width\": 320, \"height\": 480, " - "\"deviceScaleFactor\": 2, \"userAgent\": \"Mozilla/5.0 (iPhone; U; CPU iP" - "hone OS 4_2_1 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gec" - "ko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5\", \"touch\": true, \"mob" - "ile\": true},{\"title\": \"Apple iPhone 5\", \"width\": 320, \"height\": " - "568, \"deviceScaleFactor\": 2, \"userAgent\": \"Mozilla/5.0 (iPhone; CPU " - "iPhone OS 7_0 like Mac OS X; en-us) AppleWebKit/537.51.1 (KHTML, like Gec" - "ko) Version/7.0 Mobile/11A465 Safari/9537.53\", \"touch\": true, \"mobile" - "\": true},{\"title\": \"Apple iPhone 6\", \"width\": 375, \"height\": 667" - ", \"deviceScaleFactor\": 2, \"userAgent\": \"Mozilla/5.0 (iPhone; CPU iPh" - "one OS 8_0 like Mac OS X) AppleWebKit/600.1.3 (KHTML, like Gecko) Version" - "/8.0 Mobile/12A4345d Safari/600.1.4\", \"touch\": true, \"mobile\": true}" - ",{\"title\": \"Apple iPhone 6 Plus\", \"width\": 414, \"height\": 736, \"" - "deviceScaleFactor\": 3, \"userAgent\": \"Mozilla/5.0 (iPhone; CPU iPhone " - "OS 8_0 like Mac OS X) AppleWebKit/600.1.3 (KHTML, like Gecko) Version/8.0" - " Mobile/12A4345d Safari/600.1.4\", \"touch\": true, \"mobile\": true},{\"" - "title\": \"BlackBerry Z10\", \"width\": 384, \"height\": 640, \"deviceSca" - "leFactor\": 2, \"userAgent\": \"Mozilla/5.0 (BB10; Touch) AppleWebKit/537" - ".10+ (KHTML, like Gecko) Version/10.0.9.2372 Mobile Safari/537.10+\", \"t" - "ouch\": true, \"mobile\": true},{\"title\": \"BlackBerry Z30\", \"width\"" - ": 360, \"height\": 640, \"deviceScaleFactor\": 2, \"userAgent\": \"Mozill" - "a/5.0 (BB10; Touch) AppleWebKit/537.10+ (KHTML, like Gecko) Version/10.0." - "9.2372 Mobile Safari/537.10+\", \"touch\": true, \"mobile\": true},{\"tit" - "le\": \"Google Nexus 4\", \"width\": 384, \"height\": 640, \"deviceScaleF" - "actor\": 2, \"userAgent\": \"Mozilla/5.0 (Linux; Android 4.2.1; en-us; Ne" - "xus 4 Build/JOP40D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.10" - "25.166 Mobile Safari/535.19\", \"touch\": true, \"mobile\": true},{\"titl" - "e\": \"Google Nexus 5\", \"width\": 360, \"height\": 640, \"deviceScaleFa" - "ctor\": 3, \"userAgent\": \"Mozilla/5.0 (Linux; Android 4.2.1; en-us; Nex" - "us 5 Build/JOP40D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.102" - "5.166 Mobile Safari/535.19\", \"touch\": true, \"mobile\": true},{\"title" - "\": \"Google Nexus S\", \"width\": 320, \"height\": 533, \"deviceScaleFac" - "tor\": 1.5, \"userAgent\": \"Mozilla/5.0 (Linux; U; Android 2.3.4; en-us;" - " Nexus S Build/GRJ22) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 M" - "obile Safari/533.1\", \"touch\": true, \"mobile\": true},{\"title\": \"HT" - "C Evo, Touch HD, Desire HD, Desire\", \"width\": 320, \"height\": 533, \"" - "deviceScaleFactor\": 1.5, \"userAgent\": \"Mozilla/5.0 (Linux; U; Android" - " 2.2; en-us; Sprint APA9292KT Build/FRF91) AppleWebKit/533.1 (KHTML, like" - " Gecko) Version/4.0 Mobile Safari/533.1\", \"touch\": true, \"mobile\": t" - "rue},{\"title\": \"HTC One X, EVO LTE\", \"width\": 360, \"height\": 640," - " \"deviceScaleFactor\": 2, \"userAgent\": \"Mozilla/5.0 (Linux; Android 4" - ".0.3; HTC One X Build/IML74K) AppleWebKit/535.19 (KHTML, like Gecko) Chro" - "me/18.0.1025.133 Mobile Safari/535.19\", \"touch\": true, \"mobile\": tru" - "e},{\"title\": \"HTC Sensation, Evo 3D\", \"width\": 360, \"height\": 640" - ", \"deviceScaleFactor\": 1.5, \"userAgent\": \"Mozilla/5.0 (Linux; U; And" - "roid 4.0.3; en-us; HTC Sensation Build/IML74K) AppleWebKit/534.30 (KHTML," - " like Gecko) Version/4.0 Mobile Safari/534.30\", \"touch\": true, \"mobil" - "e\": true},{\"title\": \"LG Optimus 2X, Optimus 3D, Optimus Black\", \"wi" - "dth\": 320, \"height\": 533, \"deviceScaleFactor\": 1.5, \"userAgent\": " - "\"Mozilla/5.0 (Linux; U; Android 2.2; en-us; LG-P990/V08c Build/FRG83) App" - "leWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1 MMS/LG" - "-Android-MMS-V1.0/1.2\", \"touch\": true, \"mobile\": true},{\"title\": " - "\"LG Optimus G\", \"width\": 384, \"height\": 640, \"deviceScaleFactor\": " - "2, \"userAgent\": \"Mozilla/5.0 (Linux; Android 4.0; LG-E975 Build/IMM76L" - ") AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Mobile Safa" - "ri/535.19\", \"touch\": true, \"mobile\": true},{\"title\": \"LG Optimus " - "LTE, Optimus 4X HD\", \"width\": 424, \"height\": 753, \"deviceScaleFacto" - "r\": 1.7, \"userAgent\": \"Mozilla/5.0 (Linux; U; Android 2.3; en-us; LG-" - "P930 Build/GRJ90) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobil" - "e Safari/533.1\", \"touch\": true, \"mobile\": true},{\"title\": \"LG Opt" - "imus One\", \"width\": 213, \"height\": 320, \"deviceScaleFactor\": 1.5, " - "\"userAgent\": \"Mozilla/5.0 (Linux; U; Android 2.2.1; en-us; LG-MS690 Bu" - "ild/FRG83) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safar" - "i/533.1\", \"touch\": true, \"mobile\": true},{\"title\": \"Motorola Defy" - ", Droid, Droid X, Milestone\", \"width\": 320, \"height\": 569, \"deviceS" - "caleFactor\": 1.5, \"userAgent\": \"Mozilla/5.0 (Linux; U; Android 2.0; e" - "n-us; Milestone Build/ SHOLS_U2_01.03.1) AppleWebKit/530.17 (KHTML, like " - "Gecko) Version/4.0 Mobile Safari/530.17\", \"touch\": true, \"mobile\": t" - "rue},{\"title\": \"Motorola Droid 3, Droid 4, Droid Razr, Atrix 4G, Atrix" - " 2\", \"width\": 540, \"height\": 960, \"deviceScaleFactor\": 1, \"userAg" - "ent\": \"Mozilla/5.0 (Linux; U; Android 2.2; en-us; Droid Build/FRG22D) A" - "ppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1\", " - "\"touch\": true, \"mobile\": true},{\"title\": \"Motorola Droid Razr HD\"," - " \"width\": 720, \"height\": 1280, \"deviceScaleFactor\": 1, \"userAgent" - "\": \"Mozilla/5.0 (Linux; U; Android 2.3; en-us; DROID RAZR 4G Build/6.5.1" - "-73_DHD-11_M1-29) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobil" - "e Safari/533.1\", \"touch\": true, \"mobile\": true},{\"title\": \"Nokia " - "C5, C6, C7, N97, N8, X7\", \"width\": 360, \"height\": 640, \"deviceScale" - "Factor\": 1, \"userAgent\": \"NokiaN97/21.1.107 (SymbianOS/9.4; Series60/" - "5.0 Mozilla/5.0; Profile/MIDP-2.1 Configuration/CLDC-1.1) AppleWebkit/525" - " (KHTML, like Gecko) BrowserNG/7.1.4\", \"touch\": true, \"mobile\": true" - "},{\"title\": \"Nokia Lumia 7X0, Lumia 8XX, Lumia 900, N800, N810, N900\"" - ", \"width\": 320, \"height\": 533, \"deviceScaleFactor\": 1.5, \"userAgen" - "t\": \"Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0" - "; IEMobile/10.0; ARM; Touch; NOKIA; Lumia 820)\", \"touch\": true, \"mobi" - "le\": true},{\"title\": \"Samsung Galaxy Note 3\", \"width\": 360, \"heig" - "ht\": 640, \"deviceScaleFactor\": 3, \"userAgent\": \"Mozilla/5.0 (Linux;" - " U; Android 4.3; en-us; SM-N900T Build/JSS15J) AppleWebKit/534.30 (KHTML," - " like Gecko) Version/4.0 Mobile Safari/534.30\", \"touch\": true, \"mobil" - "e\": true},{\"title\": \"Samsung Galaxy Note II\", \"width\": 360, \"heig" - "ht\": 640, \"deviceScaleFactor\": 2, \"userAgent\": \"Mozilla/5.0 (Linux;" - " U; Android 4.1; en-us; GT-N7100 Build/JRO03C) AppleWebKit/534.30 (KHTML," - " like Gecko) Version/4.0 Mobile Safari/534.30\", \"touch\": true, \"mobil" - "e\": true},{\"title\": \"Samsung Galaxy Note\", \"width\": 400, \"height" - "\": 640, \"deviceScaleFactor\": 2, \"userAgent\": \"Mozilla/5.0 (Linux; U;" - " Android 2.3; en-us; SAMSUNG-SGH-I717 Build/GINGERBREAD) AppleWebKit/533." - "1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1\", \"touch\": true," - " \"mobile\": true},{\"title\": \"Samsung Galaxy S III, Galaxy Nexus\", \"" - "width\": 360, \"height\": 640, \"deviceScaleFactor\": 2, \"userAgent\": " - "\"Mozilla/5.0 (Linux; U; Android 4.0; en-us; GT-I9300 Build/IMM76D) AppleW" - "ebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30\", \"to" - "uch\": true, \"mobile\": true},{\"title\": \"Samsung Galaxy S, S II, W\"," - " \"width\": 320, \"height\": 533, \"deviceScaleFactor\": 1.5, \"userAgent" - "\": \"Mozilla/5.0 (Linux; U; Android 2.1; en-us; GT-I9000 Build/ECLAIR) A" - "ppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12" - ".2\", \"touch\": true, \"mobile\": true},{\"title\": \"Samsung Galaxy S4" - "\", \"width\": 360, \"height\": 640, \"deviceScaleFactor\": 3, \"userAgent" - "\": \"Mozilla/5.0 (Linux; Android 4.2.2; GT-I9505 Build/JDQ39) AppleWebKi" - "t/537.36 (KHTML, like Gecko) Chrome/31.0.1650.59 Mobile Safari/537.36\", " - "\"touch\": true, \"mobile\": true},{\"title\": \"Sony Xperia S, Ion\", \"" - "width\": 360, \"height\": 640, \"deviceScaleFactor\": 2, \"userAgent\": " - "\"Mozilla/5.0 (Linux; U; Android 4.0; en-us; LT28at Build/6.1.C.1.111) App" - "leWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30\", " - "\"touch\": true, \"mobile\": true},{\"title\": \"Sony Xperia Sola, U \", " - "\"width\": 480, \"height\": 854, \"deviceScaleFactor\": 1, \"userAgent\": " - "\"Mozilla/5.0 (Linux; U; Android 2.3; en-us; SonyEricssonST25i Build/6.0." - "B.1.564) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/" - "533.1\", \"touch\": true, \"mobile\": true},{\"title\": \"Sony Xperia Z, " - "Z1\", \"width\": 360, \"height\": 640, \"deviceScaleFactor\": 3, \"userAg" - "ent\": \"Mozilla/5.0 (Linux; U; Android 4.2; en-us; SonyC6903 Build/14.1." - "G.1.518) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari" - "/534.30\", \"touch\": true, \"mobile\": true},{\"title\": \"Amazon Kindle" - " Fire HDX 7″\", \"width\": 1920, \"height\": 1200, \"deviceScaleFactor\":" - " 2, \"userAgent\": \"Mozilla/5.0 (Linux; U; en-us; KFTHWI Build/JDQ39) Ap" - "pleWebKit/535.19 (KHTML, like Gecko) Silk/3.13 Safari/535.19 Silk-Acceler" - "ated=true\", \"touch\": true, \"mobile\": true},{\"title\": \"Amazon Kind" - "le Fire HDX 8.9″\", \"width\": 2560, \"height\": 1600, \"deviceScaleFacto" - "r\": 2, \"userAgent\": \"Mozilla/5.0 (Linux; U; en-us; KFAPWI Build/JDQ39" - ") AppleWebKit/535.19 (KHTML, like Gecko) Silk/3.13 Safari/535.19 Silk-Acc" - "elerated=true\", \"touch\": true, \"mobile\": true},{\"title\": \"Amazon " - "Kindle Fire (First Generation)\", \"width\": 1024, \"height\": 600, \"dev" - "iceScaleFactor\": 1, \"userAgent\": \"Mozilla/5.0 (Macintosh; U; Intel Ma" - "c OS X 10_6_3; en-us; Silk/1.0.141.16-Gen4_11004310) AppleWebkit/533.16 (" - "KHTML, like Gecko) Version/5.0 Safari/533.16 Silk-Accelerated=true\", \"t" - "ouch\": true, \"mobile\": true},{\"title\": \"Apple iPad 1 / 2 / iPad Min" - "i\", \"width\": 1024, \"height\": 768, \"deviceScaleFactor\": 1, \"userAg" - "ent\": \"Mozilla/5.0 (iPad; CPU OS 4_3_5 like Mac OS X; en-us) AppleWebKi" - "t/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8L1 Safari/6533.18.5" - "\", \"touch\": true, \"mobile\": true},{\"title\": \"Apple iPad 3 / 4\", " - "\"width\": 1024, \"height\": 768, \"deviceScaleFactor\": 2, \"userAgent\":" - " \"Mozilla/5.0 (iPad; CPU OS 7_0 like Mac OS X) AppleWebKit/537.51.1 (KHT" - "ML, like Gecko) Version/7.0 Mobile/11A465 Safari/9537.53\", \"touch\": tr" - "ue, \"mobile\": true},{\"title\": \"BlackBerry PlayBook\", \"width\": 102" - "4, \"height\": 600, \"deviceScaleFactor\": 1, \"userAgent\": \"Mozilla/5." - "0 (PlayBook; U; RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML lik" - "e Gecko) Version/7.2.1.0 Safari/536.2+\", \"touch\": true, \"mobile\": tr" - "ue},{\"title\": \"Google Nexus 10\", \"width\": 1280, \"height\": 800, \"" - "deviceScaleFactor\": 2, \"userAgent\": \"Mozilla/5.0 (Linux; Android 4.3;" - " Nexus 10 Build/JSS15Q) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29." - "0.1547.72 Safari/537.36\", \"touch\": true, \"mobile\": true},{\"title\":" - " \"Google Nexus 7 2\", \"width\": 960, \"height\": 600, \"deviceScaleFact" - "or\": 2, \"userAgent\": \"Mozilla/5.0 (Linux; Android 4.3; Nexus 7 Build/" - "JSS15Q) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.72 Safari" - "/537.36\", \"touch\": true, \"mobile\": true},{\"title\": \"Google Nexus " - "7\", \"width\": 966, \"height\": 604, \"deviceScaleFactor\": 1.325, \"use" - "rAgent\": \"Mozilla/5.0 (Linux; Android 4.3; Nexus 7 Build/JSS15Q) AppleW" - "ebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.72 Safari/537.36\", \"t" - "ouch\": true, \"mobile\": true},{\"title\": \"Motorola Xoom, Xyboard\", " - "\"width\": 1280, \"height\": 800, \"deviceScaleFactor\": 1, \"userAgent\":" - " \"Mozilla/5.0 (Linux; U; Android 3.0; en-us; Xoom Build/HRI39) AppleWebK" - "it/525.10 (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2\", \"t" - "ouch\": true, \"mobile\": true},{\"title\": \"Samsung Galaxy Tab 7.7, 8.9" - ", 10.1\", \"width\": 1280, \"height\": 800, \"deviceScaleFactor\": 1, \"u" - "serAgent\": \"Mozilla/5.0 (Linux; U; Android 2.2; en-us; SCH-I800 Build/F" - "ROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533" - ".1\", \"touch\": true, \"mobile\": true},{\"title\": \"Samsung Galaxy Tab" - "\", \"width\": 1024, \"height\": 600, \"deviceScaleFactor\": 1, \"userAge" - "nt\": \"Mozilla/5.0 (Linux; U; Android 2.2; en-us; SCH-I800 Build/FROYO) " + "[{\"title\": \"Apple iPhone 3GS\", \"width\": 320, \"height\": 480, " + "\"deviceScaleFactor\": 1, \"userAgent\": \"Mozilla/5.0 (iPhone; U; CPU " + "iPhone OS 4_2_1 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like " + "Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5\", \"touch\": true, " + "\"mobile\": true},{\"title\": \"Apple iPhone 4\", \"width\": 320, " + "\"height\": 480, \"deviceScaleFactor\": 2, \"userAgent\": \"Mozilla/5.0 " + "(iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; en-us) " + "AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 " + "Safari/6533.18.5\", \"touch\": true, \"mobile\": true},{\"title\": " + "\"Apple iPhone 5\", \"width\": 320, \"height\": 568, " + "\"deviceScaleFactor\": 2, \"userAgent\": \"Mozilla/5.0 (iPhone; CPU " + "iPhone OS 7_0 like Mac OS X; en-us) AppleWebKit/537.51.1 (KHTML, like " + "Gecko) Version/7.0 Mobile/11A465 Safari/9537.53\", \"touch\": true, " + "\"mobile\": true},{\"title\": \"Apple iPhone 6\", \"width\": 375, " + "\"height\": 667, \"deviceScaleFactor\": 2, \"userAgent\": \"Mozilla/5.0 " + "(iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/600.1.3 (KHTML, " + "like Gecko) Version/8.0 Mobile/12A4345d Safari/600.1.4\", \"touch\": " + "true, \"mobile\": true},{\"title\": \"Apple iPhone 6 Plus\", \"width\": " + "414, \"height\": 736, \"deviceScaleFactor\": 3, \"userAgent\": " + "\"Mozilla/5.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) " + "AppleWebKit/600.1.3 (KHTML, like Gecko) Version/8.0 Mobile/12A4345d " + "Safari/600.1.4\", \"touch\": true, \"mobile\": true},{\"title\": " + "\"BlackBerry Z10\", \"width\": 384, \"height\": 640, " + "\"deviceScaleFactor\": 2, \"userAgent\": \"Mozilla/5.0 (BB10; Touch) " + "AppleWebKit/537.10+ (KHTML, like Gecko) Version/10.0.9.2372 Mobile " + "Safari/537.10+\", \"touch\": true, \"mobile\": true},{\"title\": " + "\"BlackBerry Z30\", \"width\": 360, \"height\": 640, " + "\"deviceScaleFactor\": 2, \"userAgent\": \"Mozilla/5.0 (BB10; Touch) " + "AppleWebKit/537.10+ (KHTML, like Gecko) Version/10.0.9.2372 Mobile " + "Safari/537.10+\", \"touch\": true, \"mobile\": true},{\"title\": \"Google " + "Nexus 4\", \"width\": 384, \"height\": 640, \"deviceScaleFactor\": 2, " + "\"userAgent\": \"Mozilla/5.0 (Linux; Android 4.2.1; en-us; Nexus 4 " + "Build/JOP40D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 " + "Mobile Safari/535.19\", \"touch\": true, \"mobile\": true},{\"title\": " + "\"Google Nexus 5\", \"width\": 360, \"height\": 640, " + "\"deviceScaleFactor\": 3, \"userAgent\": \"Mozilla/5.0 (Linux; Android " + "4.2.1; en-us; Nexus 5 Build/JOP40D) AppleWebKit/535.19 (KHTML, like " + "Gecko) Chrome/18.0.1025.166 Mobile Safari/535.19\", \"touch\": true, " + "\"mobile\": true},{\"title\": \"Google Nexus S\", \"width\": 320, " + "\"height\": 533, \"deviceScaleFactor\": 1.5, \"userAgent\": \"Mozilla/5.0 " + "(Linux; U; Android 2.3.4; en-us; Nexus S Build/GRJ22) AppleWebKit/533.1 " + "(KHTML, like Gecko) Version/4.0 Mobile Safari/533.1\", \"touch\": true, " + "\"mobile\": true},{\"title\": \"HTC Evo, Touch HD, Desire HD, Desire\", " + "\"width\": 320, \"height\": 533, \"deviceScaleFactor\": 1.5, " + "\"userAgent\": \"Mozilla/5.0 (Linux; U; Android 2.2; en-us; Sprint " + "APA9292KT Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 " + "Mobile Safari/533.1\", \"touch\": true, \"mobile\": true},{\"title\": " + "\"HTC One X, EVO LTE\", \"width\": 360, \"height\": 640, " + "\"deviceScaleFactor\": 2, \"userAgent\": \"Mozilla/5.0 (Linux; Android " + "4.0.3; HTC One X Build/IML74K) AppleWebKit/535.19 (KHTML, like Gecko) " + "Chrome/18.0.1025.133 Mobile Safari/535.19\", \"touch\": true, \"mobile\": " + "true},{\"title\": \"HTC Sensation, Evo 3D\", \"width\": 360, \"height\": " + "640, \"deviceScaleFactor\": 1.5, \"userAgent\": \"Mozilla/5.0 (Linux; U; " + "Android 4.0.3; en-us; HTC Sensation Build/IML74K) AppleWebKit/534.30 " + "(KHTML, like Gecko) Version/4.0 Mobile Safari/534.30\", \"touch\": true, " + "\"mobile\": true},{\"title\": \"LG Optimus 2X, Optimus 3D, Optimus " + "Black\", \"width\": 320, \"height\": 533, \"deviceScaleFactor\": 1.5, " + "\"userAgent\": \"Mozilla/5.0 (Linux; U; Android 2.2; en-us; LG-P990/V08c " + "Build/FRG83) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile " + "Safari/533.1 MMS/LG-Android-MMS-V1.0/1.2\", \"touch\": true, \"mobile\": " + "true},{\"title\": \"LG Optimus G\", \"width\": 384, \"height\": 640, " + "\"deviceScaleFactor\": 2, \"userAgent\": \"Mozilla/5.0 (Linux; Android " + "4.0; LG-E975 Build/IMM76L) AppleWebKit/535.19 (KHTML, like Gecko) " + "Chrome/18.0.1025.166 Mobile Safari/535.19\", \"touch\": true, \"mobile\": " + "true},{\"title\": \"LG Optimus LTE, Optimus 4X HD\", \"width\": 424, " + "\"height\": 753, \"deviceScaleFactor\": 1.7, \"userAgent\": \"Mozilla/5.0 " + "(Linux; U; Android 2.3; en-us; LG-P930 Build/GRJ90) AppleWebKit/533.1 " + "(KHTML, like Gecko) Version/4.0 Mobile Safari/533.1\", \"touch\": true, " + "\"mobile\": true},{\"title\": \"LG Optimus One\", \"width\": 213, " + "\"height\": 320, \"deviceScaleFactor\": 1.5, \"userAgent\": \"Mozilla/5.0 " + "(Linux; U; Android 2.2.1; en-us; LG-MS690 Build/FRG83) AppleWebKit/533.1 " + "(KHTML, like Gecko) Version/4.0 Mobile Safari/533.1\", \"touch\": true, " + "\"mobile\": true},{\"title\": \"Motorola Defy, Droid, Droid X, " + "Milestone\", \"width\": 320, \"height\": 569, \"deviceScaleFactor\": 1.5, " + "\"userAgent\": \"Mozilla/5.0 (Linux; U; Android 2.0; en-us; Milestone " + "Build/ SHOLS_U2_01.03.1) AppleWebKit/530.17 (KHTML, like Gecko) " + "Version/4.0 Mobile Safari/530.17\", \"touch\": true, \"mobile\": " + "true},{\"title\": \"Motorola Droid 3, Droid 4, Droid Razr, Atrix 4G, " + "Atrix 2\", \"width\": 540, \"height\": 960, \"deviceScaleFactor\": 1, " + "\"userAgent\": \"Mozilla/5.0 (Linux; U; Android 2.2; en-us; Droid " + "Build/FRG22D) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile " + "Safari/533.1\", \"touch\": true, \"mobile\": true},{\"title\": \"Motorola " + "Droid Razr HD\", \"width\": 720, \"height\": 1280, \"deviceScaleFactor\": " + "1, \"userAgent\": \"Mozilla/5.0 (Linux; U; Android 2.3; en-us; DROID RAZR " + "4G Build/6.5.1-73_DHD-11_M1-29) AppleWebKit/533.1 (KHTML, like Gecko) " + "Version/4.0 Mobile Safari/533.1\", \"touch\": true, \"mobile\": " + "true},{\"title\": \"Nokia C5, C6, C7, N97, N8, X7\", \"width\": 360, " + "\"height\": 640, \"deviceScaleFactor\": 1, \"userAgent\": " + "\"NokiaN97/21.1.107 (SymbianOS/9.4; Series60/5.0 Mozilla/5.0; " + "Profile/MIDP-2.1 Configuration/CLDC-1.1) AppleWebkit/525 (KHTML, like " + "Gecko) BrowserNG/7.1.4\", \"touch\": true, \"mobile\": true},{\"title\": " + "\"Nokia Lumia 7X0, Lumia 8XX, Lumia 900, N800, N810, N900\", \"width\": " + "320, \"height\": 533, \"deviceScaleFactor\": 1.5, \"userAgent\": " + "\"Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; " + "IEMobile/10.0; ARM; Touch; NOKIA; Lumia 820)\", \"touch\": true, " + "\"mobile\": true},{\"title\": \"Samsung Galaxy Note 3\", \"width\": 360, " + "\"height\": 640, \"deviceScaleFactor\": 3, \"userAgent\": \"Mozilla/5.0 " + "(Linux; U; Android 4.3; en-us; SM-N900T Build/JSS15J) AppleWebKit/534.30 " + "(KHTML, like Gecko) Version/4.0 Mobile Safari/534.30\", \"touch\": true, " + "\"mobile\": true},{\"title\": \"Samsung Galaxy Note II\", \"width\": 360, " + "\"height\": 640, \"deviceScaleFactor\": 2, \"userAgent\": \"Mozilla/5.0 " + "(Linux; U; Android 4.1; en-us; GT-N7100 Build/JRO03C) AppleWebKit/534.30 " + "(KHTML, like Gecko) Version/4.0 Mobile Safari/534.30\", \"touch\": true, " + "\"mobile\": true},{\"title\": \"Samsung Galaxy Note\", \"width\": 400, " + "\"height\": 640, \"deviceScaleFactor\": 2, \"userAgent\": \"Mozilla/5.0 " + "(Linux; U; Android 2.3; en-us; SAMSUNG-SGH-I717 Build/GINGERBREAD) " "AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1\", " - "\"touch\": true, \"mobile\": true}]"; + "\"touch\": true, \"mobile\": true},{\"title\": \"Samsung Galaxy S III, " + "Galaxy Nexus\", \"width\": 360, \"height\": 640, \"deviceScaleFactor\": " + "2, \"userAgent\": \"Mozilla/5.0 (Linux; U; Android 4.0; en-us; GT-I9300 " + "Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile " + "Safari/534.30\", \"touch\": true, \"mobile\": true},{\"title\": \"Samsung " + "Galaxy S, S II, W\", \"width\": 320, \"height\": 533, " + "\"deviceScaleFactor\": 1.5, \"userAgent\": \"Mozilla/5.0 (Linux; U; " + "Android 2.1; en-us; GT-I9000 Build/ECLAIR) AppleWebKit/525.10+ (KHTML, " + "like Gecko) Version/3.0.4 Mobile Safari/523.12.2\", \"touch\": true, " + "\"mobile\": true},{\"title\": \"Samsung Galaxy S4\", \"width\": 360, " + "\"height\": 640, \"deviceScaleFactor\": 3, \"userAgent\": \"Mozilla/5.0 " + "(Linux; Android 4.2.2; GT-I9505 Build/JDQ39) AppleWebKit/537.36 (KHTML, " + "like Gecko) Chrome/31.0.1650.59 Mobile Safari/537.36\", \"touch\": true, " + "\"mobile\": true},{\"title\": \"Sony Xperia S, Ion\", \"width\": 360, " + "\"height\": 640, \"deviceScaleFactor\": 2, \"userAgent\": \"Mozilla/5.0 " + "(Linux; U; Android 4.0; en-us; LT28at Build/6.1.C.1.111) " + "AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile " + "Safari/534.30\", \"touch\": true, \"mobile\": true},{\"title\": \"Sony " + "Xperia Sola, U\", \"width\": 480, \"height\": 854, \"deviceScaleFactor\": " + "1, \"userAgent\": \"Mozilla/5.0 (Linux; U; Android 2.3; en-us; " + "SonyEricssonST25i Build/6.0.B.1.564) AppleWebKit/533.1 (KHTML, like " + "Gecko) Version/4.0 Mobile Safari/533.1\", \"touch\": true, \"mobile\": " + "true},{\"title\": \"Sony Xperia Z, Z1\", \"width\": 360, \"height\": 640, " + "\"deviceScaleFactor\": 3, \"userAgent\": \"Mozilla/5.0 (Linux; U; Android " + "4.2; en-us; SonyC6903 Build/14.1.G.1.518) AppleWebKit/534.30 (KHTML, like " + "Gecko) Version/4.0 Mobile Safari/534.30\", \"touch\": true, \"mobile\": " + "true},{\"title\": \"Amazon Kindle Fire HDX 7″\", \"width\": 1920, " + "\"height\": 1200, \"deviceScaleFactor\": 2, \"userAgent\": \"Mozilla/5.0 " + "(Linux; U; en-us; KFTHWI Build/JDQ39) AppleWebKit/535.19 (KHTML, like " + "Gecko) Silk/3.13 Safari/535.19 Silk-Accelerated=true\", \"touch\": true, " + "\"mobile\": true},{\"title\": \"Amazon Kindle Fire HDX 8.9″\", \"width\": " + "2560, \"height\": 1600, \"deviceScaleFactor\": 2, \"userAgent\": " + "\"Mozilla/5.0 (Linux; U; en-us; KFAPWI Build/JDQ39) AppleWebKit/535.19 " + "(KHTML, like Gecko) Silk/3.13 Safari/535.19 Silk-Accelerated=true\", " + "\"touch\": true, \"mobile\": true},{\"title\": \"Amazon Kindle Fire " + "(First Generation)\", \"width\": 1024, \"height\": 600, " + "\"deviceScaleFactor\": 1, \"userAgent\": \"Mozilla/5.0 (Macintosh; U; " + "Intel Mac OS X 10_6_3; en-us; Silk/1.0.141.16-Gen4_11004310) " + "AppleWebkit/533.16 (KHTML, like Gecko) Version/5.0 Safari/533.16 " + "Silk-Accelerated=true\", \"touch\": true, \"mobile\": true},{\"title\": " + "\"Apple iPad 1 / 2 / iPad Mini\", \"width\": 1024, \"height\": 768, " + "\"deviceScaleFactor\": 1, \"userAgent\": \"Mozilla/5.0 (iPad; CPU OS " + "4_3_5 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) " + "Version/5.0.2 Mobile/8L1 Safari/6533.18.5\", \"touch\": true, \"mobile\": " + "true},{\"title\": \"Apple iPad 3 / 4\", \"width\": 1024, \"height\": 768, " + "\"deviceScaleFactor\": 2, \"userAgent\": \"Mozilla/5.0 (iPad; CPU OS 7_0 " + "like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 " + "Mobile/11A465 Safari/9537.53\", \"touch\": true, \"mobile\": " + "true},{\"title\": \"BlackBerry PlayBook\", \"width\": 1024, \"height\": " + "600, \"deviceScaleFactor\": 1, \"userAgent\": \"Mozilla/5.0 (PlayBook; U; " + "RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML like Gecko) " + "Version/7.2.1.0 Safari/536.2+\", \"touch\": true, \"mobile\": " + "true},{\"title\": \"Google Nexus 10\", \"width\": 1280, \"height\": 800, " + "\"deviceScaleFactor\": 2, \"userAgent\": \"Mozilla/5.0 (Linux; Android " + "4.3; Nexus 10 Build/JSS15Q) AppleWebKit/537.36 (KHTML, like Gecko) " + "Chrome/29.0.1547.72 Safari/537.36\", \"touch\": true, \"mobile\": " + "true},{\"title\": \"Google Nexus 7 2\", \"width\": 960, \"height\": 600, " + "\"deviceScaleFactor\": 2, \"userAgent\": \"Mozilla/5.0 (Linux; Android " + "4.3; Nexus 7 Build/JSS15Q) AppleWebKit/537.36 (KHTML, like Gecko) " + "Chrome/29.0.1547.72 Safari/537.36\", \"touch\": true, \"mobile\": " + "true},{\"title\": \"Google Nexus 7\", \"width\": 966, \"height\": 604, " + "\"deviceScaleFactor\": 1.325, \"userAgent\": \"Mozilla/5.0 (Linux; " + "Android 4.3; Nexus 7 Build/JSS15Q) AppleWebKit/537.36 (KHTML, like Gecko) " + "Chrome/29.0.1547.72 Safari/537.36\", \"touch\": true, \"mobile\": " + "true},{\"title\": \"Motorola Xoom, Xyboard\", \"width\": 1280, " + "\"height\": 800, \"deviceScaleFactor\": 1, \"userAgent\": \"Mozilla/5.0 " + "(Linux; U; Android 3.0; en-us; Xoom Build/HRI39) AppleWebKit/525.10 " + "(KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2\", \"touch\": " + "true, \"mobile\": true},{\"title\": \"Samsung Galaxy Tab 7.7, 8.9, " + "10.1\", \"width\": 1280, \"height\": 800, \"deviceScaleFactor\": 1, " + "\"userAgent\": \"Mozilla/5.0 (Linux; U; Android 2.2; en-us; SCH-I800 " + "Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile " + "Safari/533.1\", \"touch\": true, \"mobile\": true},{\"title\": \"Samsung " + "Galaxy Tab\", \"width\": 1024, \"height\": 600, \"deviceScaleFactor\": 1, " + "\"userAgent\": \"Mozilla/5.0 (Linux; U; Android 2.2; en-us; SCH-I800 " + "Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile " + "Safari/533.1\", \"touch\": true, \"mobile\": true}]";
diff --git a/chrome/test/chromedriver/chrome/mobile_device_list.h b/chrome/test/chromedriver/chrome/mobile_device_list.h index 5db939c4..e2bb874 100644 --- a/chrome/test/chromedriver/chrome/mobile_device_list.h +++ b/chrome/test/chromedriver/chrome/mobile_device_list.h
@@ -1,7 +1,12 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. +// Copyright 2015 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. +// This file was generated at (2015-01-22 12:13:16.600114) by running: +// chrome/test/chromedriver/embed_mobile_devices_in_cpp.py --directory +// chrome/test/chromedriver/chrome/ +// third_party/WebKit/Source/devtools/front_end/toolbox/OverridesUI.js + #ifndef CHROME_TEST_CHROMEDRIVER_CHROME_MOBILE_DEVICE_LIST_H_ #define CHROME_TEST_CHROMEDRIVER_CHROME_MOBILE_DEVICE_LIST_H_
diff --git a/chrome/test/chromedriver/cpp_source.py b/chrome/test/chromedriver/cpp_source.py index 498fd254..c91eca9 100644 --- a/chrome/test/chromedriver/cpp_source.py +++ b/chrome/test/chromedriver/cpp_source.py
@@ -6,6 +6,7 @@ import datetime import os +import sys def WriteSource(base_name, @@ -26,7 +27,13 @@ '// Copyright %s 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.']) % datetime.date.today().year + '// found in the LICENSE file.', + '', + '// This file was generated at (%s) by running:', + '// %s']) % ( + datetime.date.today().year, + datetime.datetime.now().isoformat(' '), + ' '.join(sys.argv)) # Write header file. externs = []
diff --git a/chrome/test/chromedriver/embed_mobile_devices_in_cpp.py b/chrome/test/chromedriver/embed_mobile_devices_in_cpp.py index 2667014..327012d 100755 --- a/chrome/test/chromedriver/embed_mobile_devices_in_cpp.py +++ b/chrome/test/chromedriver/embed_mobile_devices_in_cpp.py
@@ -5,18 +5,33 @@ """Embeds standalone JavaScript snippets in C++ code. -The script requires the OverridesView file from WebKit that lists the known -mobile devices to be passed in as the only argument. The list of known devices -will be written to a C-style string to be parsed with JSONReader. +The script requires the devtools/front_end/toolbox/OverridesUI.js file from +WebKit that lists the known mobile devices to be passed in as the only argument. +The list of known devices will be written to a C-style string to be parsed with +JSONReader. """ import optparse import os +import re +import subprocess import sys import cpp_source +def quotizeKeys(s, keys): + """Returns the string s with each instance of each key wrapped in quotes. + + Args: + s: a string containing keys that need to be wrapped in quotes. + keys: an iterable of keys to be wrapped in quotes in the string. + """ + for key in keys: + s = re.sub('%s: ' % key, '"%s": ' % key, s) + return s + + def main(): parser = optparse.OptionParser() parser.add_option( @@ -30,8 +45,10 @@ with open(file_name, 'r') as f: for line in f: if not inside_list: - if 'WebInspector.OverridesUI._phones = [' in line or \ - 'WebInspector.OverridesUI._tablets = [' in line: + if 'WebInspector.OverridesUI._phones = [' in line: + inside_list = True + if 'WebInspector.OverridesUI._tablets = [' in line: + devices += ',' inside_list = True else: if line.strip() == '];': @@ -39,11 +56,19 @@ continue devices += line.strip() + output_dir = 'chrome/test/chromedriver/chrome' devices += ']' + devices = quotizeKeys(devices, + ['title', 'width', 'height', 'deviceScaleFactor', + 'userAgent', 'touch', 'mobile']) cpp_source.WriteSource('mobile_device_list', - 'chrome/test/chromedriver/chrome', + output_dir, options.directory, {'kMobileDevices': devices}) + clang_format = ['clang-format', '-i'] + subprocess.Popen(clang_format + ['%s/mobile_device_list.cc' % output_dir]) + subprocess.Popen(clang_format + ['%s/mobile_device_list.h' % output_dir]) + if __name__ == '__main__': sys.exit(main())
diff --git a/chrome/test/chromedriver/test/run_py_tests.py b/chrome/test/chromedriver/test/run_py_tests.py index 1983551..d64b0a9 100755 --- a/chrome/test/chromedriver/test/run_py_tests.py +++ b/chrome/test/chromedriver/test/run_py_tests.py
@@ -729,9 +729,22 @@ def testConsoleLogSources(self): self._driver.Load(self.GetHttpUrlForFile('/chromedriver/console_log.html')) logs = self._driver.GetLog('browser') - self.assertEquals(len(logs), 2) - self.assertEquals(logs[0]['source'], 'network') - self.assertEquals(logs[1]['source'], 'javascript') + + self.assertEqual('network', logs[0]['source']) + self.assertTrue('nonexistent.png' in logs[0]['message']) + self.assertTrue('404' in logs[0]['message']) + + self.assertEqual('javascript', logs[1]['source']) + self.assertTrue('TypeError' in logs[1]['message']) + + # Sometimes, we also get an error for a missing favicon. + if len(logs) > 2: + self.assertEqual('network', logs[2]['source']) + self.assertTrue('favicon.ico' in logs[2]['message']) + self.assertTrue('404' in logs[2]['message']) + self.assertEqual(3, len(logs)) + else: + self.assertEqual(2, len(logs)) def testAutoReporting(self): self.assertFalse(self._driver.IsAutoReporting())
diff --git a/chrome/test/chromedriver/test/test_expectations b/chrome/test/chromedriver/test/test_expectations index 0b22fa8..dab6122 100644 --- a/chrome/test/chromedriver/test/test_expectations +++ b/chrome/test/chromedriver/test/test_expectations
@@ -198,16 +198,15 @@ # https://code.google.com/p/chromedriver/issues/detail?id=955 'TypingTest.testShiftSelectionDeletes', + + # https://code.google.com/p/chromedriver/issues/detail?id=998 + 'ImplicitWaitTest.testShouldImplicitlyWaitForASingleElement', + 'ImplicitWaitTest.testShouldReturnAfterFirstAttemptToFindManyAfterDisablingImplicitWaits', ] _OS_NEGATIVE_FILTER['android:chrome_stable'] = ( _OS_NEGATIVE_FILTER['android:chrome']) _OS_NEGATIVE_FILTER['android:chrome_beta'] = ( - _OS_NEGATIVE_FILTER['android:chrome'] + [ - # https://code.google.com/p/chromedriver/issues/detail?id=998 - 'ImplicitWaitTest.testShouldImplicitlyWaitForASingleElement', - # https://code.google.com/p/chromedriver/issues/detail?id=1017 - 'ImplicitWaitTest.testShouldReturnAfterFirstAttemptToFindManyAfterDisablingImplicitWaits', - ] + _OS_NEGATIVE_FILTER['android:chrome'] ) _OS_NEGATIVE_FILTER['android:chrome_shell'] = ( _OS_NEGATIVE_FILTER['android:chrome'])
diff --git a/chrome/test/data/chromedriver/console_log.html b/chrome/test/data/chromedriver/console_log.html index 61175756..1387c7e 100644 --- a/chrome/test/data/chromedriver/console_log.html +++ b/chrome/test/data/chromedriver/console_log.html
@@ -8,6 +8,6 @@ </script> </head> <body onload="onLoad()"> - <img src="http://google.com/nonexistent.png"> + <img src="/chromedriver/nonexistent.png"> </body> </html>
diff --git a/chrome/test/data/chromedriver/multiline.html b/chrome/test/data/chromedriver/multiline.html index f85d3e86..13f05bc 100644 --- a/chrome/test/data/chromedriver/multiline.html +++ b/chrome/test/data/chromedriver/multiline.html
@@ -5,12 +5,20 @@ <title>A multi-line link</title> </head> <body> - <p style="max-width: 15em"> - mmmmmmmmmmm <a href="#top">mmmmmm mmmmmm</a> mmmmmmmmmmm - </p> <p> This test page contains a link that spans two lines. The center of the bounding box of the link is not inside the link element. </p> + <p style="max-width: 15em"> + <span id="filler"></span> + <a href="#top">a link</a> + </p> + <script> + var filler = document.getElementById('filler'); + var link = document.getElementsByTagName('a')[0]; + do { + filler.innerHTML += 'x'; + } while (link.getClientRects().length < 2); + </script> </body> </html>
diff --git a/chrome/test/data/extensions/api_test/content_settings/standard/test.js b/chrome/test/data/extensions/api_test/content_settings/standard/test.js index 7017892..35835d24 100644 --- a/chrome/test/data/extensions/api_test/content_settings/standard/test.js +++ b/chrome/test/data/extensions/api_test/content_settings/standard/test.js
@@ -13,7 +13,8 @@ "plugins": "allow", "popups": "block", "location": "ask", - "notifications": "ask" + "notifications": "ask", + "mouselock": "ask", }; var settings = { @@ -23,7 +24,8 @@ "plugins": "block", "popups": "allow", "location": "block", - "notifications": "block" + "notifications": "block", + "mouselock": "block" }; Object.prototype.forEach = function(f) {
diff --git a/chrome/test/data/extensions/api_test/hotword_private/onDeleteSpeakerModel/manifest.json b/chrome/test/data/extensions/api_test/hotword_private/onDeleteSpeakerModel/manifest.json new file mode 100644 index 0000000..89dd7bc8 --- /dev/null +++ b/chrome/test/data/extensions/api_test/hotword_private/onDeleteSpeakerModel/manifest.json
@@ -0,0 +1,12 @@ +{ + // chrome-extension://cpfhkdbjfdgdebcjlifoldbijinjfifp/ + "key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDCXAxIB5iu+XGtMYYJgSwMrqO+zNa3FlWeMJLOV+U1T2VL6wDU3WD9YNlioI6a6wG49AFquEbRxQwwxlvAZC1c95LBvRlnQAkEVum0KbrJ8WHTxxDEPOfITE0J1AP5j8V0WQ9jbYvUxgefIPhDPXHpdPRAxDotygTrPa33x1075wIDAQAB", + "name": "Hotword Private Test Extension", + "version": "0.1", + "manifest_version": 2, + "description": "Browser tests for chrome.hotword_private API", + "background" : { + "scripts": ["test.js"] + }, + "permissions": ["hotwordPrivate"] +}
diff --git a/chrome/test/data/extensions/api_test/hotword_private/onDeleteSpeakerModel/test.js b/chrome/test/data/extensions/api_test/hotword_private/onDeleteSpeakerModel/test.js new file mode 100644 index 0000000..aaa08e0 --- /dev/null +++ b/chrome/test/data/extensions/api_test/hotword_private/onDeleteSpeakerModel/test.js
@@ -0,0 +1,15 @@ +// 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. + +chrome.test.runTests([ + function onDeleteSpeakerModel() { + chrome.hotwordPrivate.onDeleteSpeakerModel.addListener(function () { + chrome.test.sendMessage("notification"); + chrome.test.succeed(); + }); + chrome.hotwordPrivate.getAudioHistoryEnabled( + chrome.test.callbackPass(function(state) {})); + chrome.test.sendMessage("ready"); + } +]);
diff --git a/chrome/test/data/extensions/platform_apps/web_view/shim/main.js b/chrome/test/data/extensions/platform_apps/web_view/shim/main.js index ed2e6ee..91e7db8 100644 --- a/chrome/test/data/extensions/platform_apps/web_view/shim/main.js +++ b/chrome/test/data/extensions/platform_apps/web_view/shim/main.js
@@ -178,8 +178,9 @@ webview.setAttribute('maxheight', 110); webview.addEventListener('sizechanged', function(e) { - embedder.test.assertEq(0, e.oldWidth); - embedder.test.assertEq(0, e.oldHeight); + // The old size should be the default size of the webview, which at the time + // of writing this comment is 300 x 300, but is not important to this test + // and could change in the future, so it is not checked here. embedder.test.assertTrue(e.newWidth >= 200 && e.newWidth <= 210); embedder.test.assertTrue(e.newHeight >= 100 && e.newHeight <= 110); embedder.test.succeed(); @@ -198,6 +199,8 @@ var webview = document.createElement('webview'); var step = 1; + var autosizeWidth = -1; + var autosizeHeight = -1; var sizeChangeHandler = function(e) { switch (step) { case 1: @@ -207,14 +210,15 @@ embedder.test.assertTrue(e.newWidth >= 60 && e.newWidth <= 70); embedder.test.assertTrue(e.newHeight >= 110 && e.newHeight <= 120); - // Remove autosize attribute and expect webview to return to its - // original size. + // Remove autosize attribute and expect webview to retain the same size. + autosizeWidth = e.newWidth; + autosizeHeight = e.newHeight; webview.removeAttribute('autosize'); break; case 2: - // Expect 50x100. - embedder.test.assertEq(50, e.newWidth); - embedder.test.assertEq(100, e.newHeight); + // Expect the autosized size. + embedder.test.assertEq(autosizeWidth, e.newWidth); + embedder.test.assertEq(autosizeHeight, e.newHeight); embedder.test.succeed(); break;
diff --git a/chrome/test/data/nacl/nacl_test_data.gyp b/chrome/test/data/nacl/nacl_test_data.gyp index 9494caa..63c8545 100644 --- a/chrome/test/data/nacl/nacl_test_data.gyp +++ b/chrome/test/data/nacl/nacl_test_data.gyp
@@ -18,7 +18,6 @@ 'test_files': [ # TODO(ncbray) move into chrome/test/data/nacl when all tests are # converted. - '<(DEPTH)/ppapi/native_client/tests/ppapi_browser/progress_event_listener.js', '<(DEPTH)/ppapi/native_client/tools/browser_tester/browserdata/nacltest.js', # Files that aren't assosiated with any particular executable. @@ -38,6 +37,7 @@ 'crash/ppapi_crash_off_main_thread.html', 'load_util.js', 'manifest_file/test_file.txt', + 'progress_event_listener.js', ], }, 'conditions': [
diff --git a/ppapi/native_client/tests/ppapi_browser/progress_event_listener.js b/chrome/test/data/nacl/progress_event_listener.js similarity index 100% rename from ppapi/native_client/tests/ppapi_browser/progress_event_listener.js rename to chrome/test/data/nacl/progress_event_listener.js
diff --git a/chrome/test/data/pdf/bookmarks_test.js b/chrome/test/data/pdf/bookmarks_test.js new file mode 100644 index 0000000..43a679b --- /dev/null +++ b/chrome/test/data/pdf/bookmarks_test.js
@@ -0,0 +1,39 @@ +// Copyright 2015 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. + +var tests = [ + /** + * Test that the correct bookmarks were loaded for test-bookmarks.pdf. + */ + function testHasCorrectBookmarks() { + var bookmarks = viewer.bookmarks; + + // Load all relevant bookmarks. + chrome.test.assertEq(2, bookmarks.length); + var firstBookmark = bookmarks[0]; + var secondBookmark = bookmarks[1]; + chrome.test.assertEq(1, firstBookmark.children.length); + chrome.test.assertEq(0, secondBookmark.children.length); + var firstNestedBookmark = firstBookmark.children[0]; + + // Check titles. + chrome.test.assertEq('First Section', + firstBookmark.title); + chrome.test.assertEq('First Subsection', + firstNestedBookmark.title); + chrome.test.assertEq('Second Section', + secondBookmark.title); + // Check pages. + chrome.test.assertEq(0, firstBookmark.page); + chrome.test.assertEq(1, firstNestedBookmark.page); + chrome.test.assertEq(2, secondBookmark.page); + + chrome.test.succeed(); + } +]; + +var scriptingAPI = new PDFScriptingAPI(window, window); +scriptingAPI.setLoadCallback(function() { + chrome.test.runTests(tests); +});
diff --git a/chrome/test/data/pdf/test-bookmarks.pdf b/chrome/test/data/pdf/test-bookmarks.pdf new file mode 100644 index 0000000..a72eea1 --- /dev/null +++ b/chrome/test/data/pdf/test-bookmarks.pdf Binary files differ
diff --git a/chrome/test/data/webrtc/webrtc-simulcast.html b/chrome/test/data/webrtc/webrtc-simulcast.html new file mode 100644 index 0000000..352bd87 --- /dev/null +++ b/chrome/test/data/webrtc/webrtc-simulcast.html
@@ -0,0 +1,243 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> + <title>WebRTC Simulcast Test</title> + <style> + video { + border:5px solid black; + } + button { + font: 18px sans-serif; + padding: 8px; + } + </style> +</head> +<body> + <video id="localVideo" autoplay></video> + <!-- These video tags and canvases should match the stream labels returned by + PC_SERVER_REMOTE_OFFER. The canvases are there for video detection. --!> + <video id="remoteVideo1" autoplay></video> + <video id="remoteVideo2" autoplay></video> + <video id="remoteVideo3" autoplay></video> + <canvas id="remoteVideo1-canvas" autoplay style="display:none"></video> + <canvas id="remoteVideo2-canvas" autoplay style="display:none"></video> + <canvas id="remoteVideo3-canvas" autoplay style="display:none"></video> + + <script type="text/javascript" src="webrtc_test_utilities.js"></script> + <script type="text/javascript"> + +var pcClient, pcServer; +var localStream; +var remoteVideoUrls = []; +var serverAnswer; + +// When all required video tags are playing video, succeed the test. +setAllEventsOccuredHandler(function() { + returnToTest('OK'); +}); + +// Checks that we can get a simulcast stream call up on VGA. +function testVgaReturnsTwoSimulcastStreams() { + initialize(); + openCamera(640, 480); + + // For VGA we should get a QVGA and VGA stream. The video tags are named after + // the stream IDs which are defined in PC_SERVER_REMOTE_OFFER. + waitForVideo('remoteVideo1'); + waitForVideo('remoteVideo2'); +} + +// Template for the local offer, representing a single input stream backing +// 3 different SSRCs, all in one SIM ssrc-group. +function makeClientOffer() { + var lines = [ + 'v=0', + 'o=- 0 3 IN IP4 127.0.0.1', + 's=-', + 't=0 0', + 'm=video 1 RTP/SAVPF 100', + 'a=rtcp:1 IN IP4 0.0.0.0', + 'a=ice-ufrag:6HHHdzzeIhkE0CKj', + 'a=ice-pwd:XYDGVpfvklQIEnZ6YnyLsAew', + 'a=sendonly', + 'a=mid:video', + 'a=crypto:1 AES_CM_128_HMAC_SHA1_80 ' + + 'inline:Rlz8z1nMtwq9VF7j06kTc7uyio1iYuEdeZ7z1P9E', + 'a=rtpmap:100 VP8/30', + 'a=fmtp:100 x-google-start-bitrate=100000', + 'a=fmtp:100 x-google-min-bitrate=80000', + 'a=x-google-flag:conference' + ]; + + if (localStream) { + var videoTracks = localStream.getVideoTracks(); + if (videoTracks.length > 0) { + trace('Using Video device: ' + videoTracks[0].id); + } else { + trace('WARNING: No video device!'); + return lines.join('\n'); + } + + lines = lines.concat([ + 'a=ssrc-group:SIM 1 2 3', + 'a=ssrc:1 cname:localVideo', + 'a=ssrc:1 msid:' + localStream.id + ' ' + videoTracks[0].id, + 'a=ssrc:2 cname:localVideo', + 'a=ssrc:2 msid:' + localStream.id + ' ' + videoTracks[0].id, + 'a=ssrc:3 cname:localVideo', + 'a=ssrc:3 msid:' + localStream.id + ' ' + videoTracks[0].id + ]); + } + lines.push(''); + + return new RTCSessionDescription({ + 'type': 'offer', + 'sdp': lines.join('\n') + }); +} + +// Remote perspective on that offer, representing each SSRC as a distinct +// (non-synchronized) output video stream. +var PC_SERVER_REMOTE_OFFER = [ + 'v=0', + 'o=- 0 3 IN IP4 127.0.0.1', + 's=-', + 't=0 0', + 'm=video 1 RTP/SAVPF 100', + 'a=sendonly', + 'a=mid:video', + 'a=rtcp:1 IN IP4 0.0.0.0', + 'a=ice-ufrag:6HHHdzzeIhkE0CKj', + 'a=ice-pwd:XYDGVpfvklQIEnZ6YnyLsAew', + 'a=crypto:1 AES_CM_128_HMAC_SHA1_80 ' + + 'inline:Rlz8z1nMtwq9VF7j06kTc7uyio1iYuEdeZ7z1P9E', + 'a=rtpmap:100 VP8/30', + 'a=x-google-flag:conference', + 'a=fmtp:100 x-google-start-bitrate=100000', + 'a=fmtp:100 x-google-min-bitrate=80000', + 'a=ssrc:1 cname:remoteVideo1', + 'a=ssrc:1 msid:remoteVideo1 remoteVideo1v0', + 'a=ssrc:2 cname:remoteVideo2', + 'a=ssrc:2 msid:remoteVideo2 remoteVideo2v0', + 'a=ssrc:3 cname:remoteVideo3', + 'a=ssrc:3 msid:remoteVideo3 remoteVideo3v0', + '' +].join('\n'); + +function trace(text) { + // This function is used for logging. + if (text[text.length - 1] == '\n') { + text = text.substring(0, text.length - 1); + } + console.log((performance.now() / 1000).toFixed(3) + ': ' + text); +} + +function initialize() { + trace('Setting up for a new call.'); + var servers = null; + var constraints = {'mandatory': {'DtlsSrtpKeyAgreement': false}}; + pcClient = new webkitRTCPeerConnection(servers, constraints); + trace('Created local peer connection object pcClient'); + pcClient.onicecandidate = onClientIceCandidate; + pcServer = new webkitRTCPeerConnection(servers, constraints); + trace('Created remote peer connection object pcServer'); + pcServer.onicecandidate = onServerIceCandidate; + pcServer.onaddstream = onServerGotStream; + + var pcClientInitialOffer = makeClientOffer(); + trace('Setting initial local Offer to:\n' + pcClientInitialOffer); + pcClient.setLocalDescription(pcClientInitialOffer, + setServerRemoteDescription); +} + +function gotStream(stream) { + trace('Received local stream'); + localVideo.src = webkitURL.createObjectURL(stream); + localStream = stream; + pcClient.addStream(localStream); + renegotiateClient(); +} + +function didntGetStream(err) { + returnToTest('Unexpectedly failed to acquire user media: ' + err); +} + +function openCamera(width, height) { + if (localStream) { + pcClient.removeStream(localStream); + localStream.stop(); + localStream = null; + } + navigator.webkitGetUserMedia({ + audio: false, + video: {'mandatory': {'minWidth': width, 'maxWidth': width, + 'minHeight': height, 'maxHeight': height}} + }, gotStream, didntGetStream); +} + +function renegotiateClient() { + pcClient.setLocalDescription(makeClientOffer(), function() { + pcClient.setRemoteDescription(serverAnswer); + }); +} + +function setServerRemoteDescription() { + trace('Setting remote Offer to:\n' + PC_SERVER_REMOTE_OFFER); + pcServer.setRemoteDescription(new RTCSessionDescription({ + 'type': 'offer', + 'sdp': PC_SERVER_REMOTE_OFFER + }), afterSetServerRemoteDescription); +} + +function afterSetServerRemoteDescription() { + pcServer.createAnswer(onServerAnswer); +} + +function onServerAnswer(desc) { + desc.sdp += 'a=x-google-flag:conference\n'; + serverAnswer = desc; + trace('Setting both Answers to:\n' + desc.sdp); + pcServer.setLocalDescription(desc); + pcClient.setRemoteDescription(desc); +} + +function onServerGotStream(e) { + trace('Received remote stream: ' + e.stream.label + + '; looking up corresponding video tag.'); + + var remoteVideo = $(e.stream.label); + if (!remoteVideo) { + // All streams we receive must have a corresponding video tag defined in the + // html, otherwise we can't detect video in it. + throw 'Received video with unexpected id ' + e.stream.label; + } + remoteVideo.src = webkitURL.createObjectURL(e.stream); +} + +function onClientIceCandidate(event) { + if (event.candidate) { + pcServer.addIceCandidate(event.candidate); + trace('Local ICE candidate:\n' + event.candidate.candidate); + } +} + +function onServerIceCandidate(event) { + if (event.candidate) { + pcClient.addIceCandidate(event.candidate); + trace('Remote ICE candidate:\n' + event.candidate.candidate); + } +} + +function returnToTest(message) { + if (!window.domAutomationController) + throw 'Expected to run in an automated context.'; + window.domAutomationController.send(message); +} + +$ = function(id) { + return document.getElementById(id); +}; + + </script> +</body>
diff --git a/chrome/test/data/webrtc/webrtc_test_utilities.js b/chrome/test/data/webrtc/webrtc_test_utilities.js new file mode 100644 index 0000000..5dbca628 --- /dev/null +++ b/chrome/test/data/webrtc/webrtc_test_utilities.js
@@ -0,0 +1,107 @@ +// Copyright (c) 2015 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. + +// This file contains duplicated functions in of +// content/test/data/media/webrtc_test_utilities.js +// TODO(phoglund): Eliminate this copy and rewrite the +// WebRtcBrowserTest.TestVgaReturnsTwoSimulcastStreams test to use the browser +// tests style instead. + +// These must match with how the video and canvas tags are declared in html. +const VIDEO_TAG_WIDTH = 320; +const VIDEO_TAG_HEIGHT = 240; + +// Number of test events to occur before the test pass. When the test pass, +// the function gAllEventsOccured is called. +var gNumberOfExpectedEvents = 0; + +// Number of events that currently have occurred. +var gNumberOfEvents = 0; + +var gAllEventsOccured = function () {}; + +// Use this function to set a function that will be called once all expected +// events has occurred. +function setAllEventsOccuredHandler(handler) { + gAllEventsOccured = handler; +} + +// See comments on waitForVideo. +function detectVideoIn(videoElementName, callback) { + var width = VIDEO_TAG_WIDTH; + var height = VIDEO_TAG_HEIGHT; + var videoElement = $(videoElementName); + var canvas = $(videoElementName + '-canvas'); + var waitVideo = setInterval(function() { + var context = canvas.getContext('2d'); + context.drawImage(videoElement, 0, 0, width, height); + var pixels = context.getImageData(0, 0, width, height).data; + + if (isVideoPlaying(pixels, width, height)) { + clearInterval(waitVideo); + callback(); + } + }, 100); +} + +/** + * Blocks test success until the provided videoElement has playing video. + * + * @param videoElementName The id of the video element. There must also be a + * canvas somewhere in the DOM tree with the id |videoElementName|-canvas. + * @param callback The callback to call. + */ +function waitForVideo(videoElement) { + document.title = 'Waiting for video...'; + addExpectedEvent(); + detectVideoIn(videoElement, function () { eventOccured(); }); +} + +/** + * Blocks test success until the provided peerconnection reports the signaling + * state 'stable'. + * + * @param peerConnection The peer connection to look at. + */ +function waitForConnectionToStabilize(peerConnection) { + addExpectedEvent(); + var waitForStabilization = setInterval(function() { + if (peerConnection.signalingState == 'stable') { + clearInterval(waitForStabilization); + eventOccured(); + } + }, 100); +} + +/** + * Adds an expectation for an event to occur at some later point. You may call + * this several times per test, which will each add an expected event. Once all + * events have occurred, we'll call the "all events occurred" handler which will + * generally succeed the test or move the test to the next phase. + */ +function addExpectedEvent() { + ++gNumberOfExpectedEvents; +} + +// See comment on addExpectedEvent. +function eventOccured() { + ++gNumberOfEvents; + if (gNumberOfEvents == gNumberOfExpectedEvents) { + gAllEventsOccured(); + } +} + +// This very basic video verification algorithm will be satisfied if any +// pixels are nonzero in a small sample area in the middle. It relies on the +// assumption that a video element with null source just presents zeroes. +function isVideoPlaying(pixels, width, height) { + // Sample somewhere near the middle of the image. + var middle = width * height / 2; + for (var i = 0; i < 20; i++) { + if (pixels[middle + i] > 0) { + return true; + } + } + return false; +}
diff --git a/chrome/test/data/webui/certificate_viewer_ui_test-inl.h b/chrome/test/data/webui/certificate_viewer_ui_test-inl.h index 4b5356b..dc333cc 100644 --- a/chrome/test/data/webui/certificate_viewer_ui_test-inl.h +++ b/chrome/test/data/webui/certificate_viewer_ui_test-inl.h
@@ -22,7 +22,7 @@ class CertificateViewerUITest : public WebUIBrowserTest { public: CertificateViewerUITest(); - virtual ~CertificateViewerUITest(); + ~CertificateViewerUITest() override; protected: void CreateCertViewerDialog();
diff --git a/chrome/test/ppapi/ppapi_browsertest.cc b/chrome/test/ppapi/ppapi_browsertest.cc index a2e3912..ec257f65 100644 --- a/chrome/test/ppapi/ppapi_browsertest.cc +++ b/chrome/test/ppapi/ppapi_browsertest.cc
@@ -1304,13 +1304,7 @@ IN_PROC_BROWSER_TEST_F(PPAPINaClNewlibTest, View) { RUN_VIEW_SUBTESTS; } -// Disabled due to flakiness under MSAN. See http://crbug.com/450908. -#if defined(MEMORY_SANITIZER) -#define MAYBE_View DISABLED_View -#else -#define MAYBE_View View -#endif -IN_PROC_BROWSER_TEST_F(PPAPINaClGLibcTest, MAYBE_GLIBC(MAYBE_View)) { +IN_PROC_BROWSER_TEST_F(PPAPINaClGLibcTest, MAYBE_GLIBC(View)) { RUN_VIEW_SUBTESTS; } IN_PROC_BROWSER_TEST_F(PPAPINaClPNaClTest, View) {
diff --git a/chrome/test/remoting/me2me_browsertest.cc b/chrome/test/remoting/me2me_browsertest.cc index 43d0cf1..cc1415a1 100644 --- a/chrome/test/remoting/me2me_browsertest.cc +++ b/chrome/test/remoting/me2me_browsertest.cc
@@ -154,6 +154,16 @@ Cleanup(); } +IN_PROC_BROWSER_TEST_F(Me2MeBrowserTest, + MANUAL_Me2Me_Disable_Remote_Connection) { + SetUpTest(); + + DisableRemoteConnection(); + EXPECT_FALSE(IsLocalHostReady()); + + Cleanup(); +} + void Me2MeBrowserTest::SetupForRemoteHostTest() { VerifyInternetAccess(); OpenClientBrowserPage();
diff --git a/chrome/test/remoting/remote_desktop_browsertest.cc b/chrome/test/remoting/remote_desktop_browsertest.cc index 43e76bdc..1c9528ce 100644 --- a/chrome/test/remoting/remote_desktop_browsertest.cc +++ b/chrome/test/remoting/remote_desktop_browsertest.cc
@@ -907,4 +907,35 @@ "document.getElementById(\"" + element_name + "\").disabled"); } +bool RemoteDesktopBrowserTest::IsAppModeEqualTo(const std::string& mode) { + return ExecuteScriptAndExtractBool( + "remoting.currentMode == " + mode); +} + +void RemoteDesktopBrowserTest::DisableRemoteConnection() { + ConditionalTimeoutWaiter hostReadyWaiter( + base::TimeDelta::FromSeconds(5), + base::TimeDelta::FromMilliseconds(500), + base::Bind(&RemoteDesktopBrowserTest::IsLocalHostReady, this)); + EXPECT_TRUE(hostReadyWaiter.Wait()); + + ClickOnControl("stop-daemon"); + + ConditionalTimeoutWaiter setupDoneWaiter( + base::TimeDelta::FromSeconds(30), + base::TimeDelta::FromMilliseconds(500), + base::Bind(&RemoteDesktopBrowserTest::IsAppModeEqualTo, + this, "remoting.AppMode.HOST_SETUP_DONE")); + EXPECT_TRUE(setupDoneWaiter.Wait()); + + ClickOnControl("host-config-done-dismiss"); + + ConditionalTimeoutWaiter homeWaiter( + base::TimeDelta::FromSeconds(5), + base::TimeDelta::FromMilliseconds(500), + base::Bind(&RemoteDesktopBrowserTest::IsAppModeEqualTo, + this, "remoting.AppMode.HOME")); + EXPECT_TRUE(homeWaiter.Wait()); +} + } // namespace remoting
diff --git a/chrome/test/remoting/remote_desktop_browsertest.h b/chrome/test/remoting/remote_desktop_browsertest.h index edbd0752..5455a2f 100644 --- a/chrome/test/remoting/remote_desktop_browsertest.h +++ b/chrome/test/remoting/remote_desktop_browsertest.h
@@ -347,6 +347,12 @@ static bool IsHostActionComplete( content::WebContents* client_web_content, std::string host_action_var); + // Test if the remoting app mode is equal to the given mode + bool IsAppModeEqualTo(const std::string& mode); + + // Disable remote connection while the remote connection is enabled + void DisableRemoteConnection(); + private: // Fields
diff --git a/chrome_elf/BUILD.gn b/chrome_elf/BUILD.gn new file mode 100644 index 0000000..b58c829 --- /dev/null +++ b/chrome_elf/BUILD.gn
@@ -0,0 +1,205 @@ +# Copyright 2015 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. + +import("//chrome/version.gni") +import("//testing/test.gni") + +process_version("chrome_elf_resources") { + source = "//chrome/app/chrome_version.rc.version" + output = "$target_gen_dir/chrome_elf_version.rc" + extra_args = [ + "-f", + rebase_path("chrome_elf.ver"), + ] +} + +shared_library("chrome_elf") { + sources = [ + "chrome_elf_main.cc", + "chrome_elf_main.h", + "$target_gen_dir/chrome_elf_version.rc", + ] + deps = [ + ":blacklist", + ":breakpad", + ":lib", + ":chrome_elf_resources", + ] + configs += [ "//build/config/win:windowed" ] + configs -= [ "//build/config/win:console" ] + ldflags = [ + "/NODEFAULTLIB:user32.lib", + "/DEF:" + rebase_path("chrome_elf.def"), + ] + if (cpu_arch == "x86") { + # Don"t set an x64 base address (to avoid breaking HE-ASLR). + ldflags += [ "/BASE:0x01c20000" ] + } +} + +source_set("lib") { + sources = [ + "create_file/chrome_create_file.cc", + "create_file/chrome_create_file.h", + "ntdll_cache.cc", + "ntdll_cache.h", + ] + deps = [ + ":common", + "//base:base_static", + "//sandbox", + ] +} + +source_set("constants") { + sources = [ + "chrome_elf_constants.cc", + "chrome_elf_constants.h", + ] +} + +source_set("common") { + deps = [ + ":constants", + ] + sources = [ + "chrome_elf_types.h", + "chrome_elf_util.cc", + "chrome_elf_util.h", + "thunk_getter.cc", + "thunk_getter.h", + ] +} + +source_set("breakpad") { + include_dirs = [ "$target_gen_dir" ] + sources = [ + "breakpad.cc", + "breakpad.h", + ] + deps = [ + ":common", + "//breakpad:breakpad_handler", + "//chrome:version_header", + ] +} + +if (is_component_build) { + shared_library("chrome_redirects") { + sources = [ + "chrome_redirects_main.cc", + ] + deps = [ + ":lib", + ] + configs += [ "//build/config/win:windowed" ] + ldflags = [ "/DEF:" + rebase_path("chrome_redirects.def") ] + + if (cpu_arch == "x86") { + # Don't set an x64 base address (to avoid breaking HE-ASLR). + ldflags += [ "/BASE:0x01c20000" ] + } + } +} + +source_set("dll_hash") { + deps = [ + "//base", + ] + sources = [ + "dll_hash/dll_hash.cc", + "dll_hash/dll_hash.h", + ] +} + +executable("dll_hash_main") { + deps = [ + ":dll_hash", + ] + sources = [ + "dll_hash/dll_hash_main.cc", + ] +} + +static_library("blacklist") { + sources = [ + "blacklist/blacklist.cc", + "blacklist/blacklist.h", + "blacklist/blacklist_interceptions.cc", + "blacklist/blacklist_interceptions.h", + ] + deps = [ + # Depend on base_static, but do NOT take a dependency on base.gyp:base + # as that would risk pulling in base's link-time dependencies which + # chrome_elf cannot do. + ":breakpad", + ":constants", + "//base:base_static", + "//sandbox:sandbox", + ] +} + +test("chrome_elf_unittests") { + output_name = "chrome_elf_unittests" + sources = [ + "blacklist/test/blacklist_test.cc", + "chrome_elf_util_unittest.cc", + "create_file/chrome_create_file_unittest.cc", + "elf_imports_unittest.cc", + "ntdll_cache_unittest.cc", + ] + include_dirs = [ "$target_gen_dir" ] + deps = [ + ":blacklist", + ":blacklist_test_main_dll", + ":lib", + "//base", + "//base/test:run_all_unittests", + "//base/test:test_support", + "//sandbox", + "//testing/gtest", + ] + data_deps = [ + ":blacklist_test_dll_1", + ":blacklist_test_dll_2", + ":blacklist_test_dll_3", + ":chrome_elf", + "//chrome", + ] +} + +shared_library("blacklist_test_main_dll") { + sources = [ + "blacklist/test/blacklist_test_main_dll.cc", + ] + deps = [ + "//base", + ":blacklist", + ] + ldflags = + [ "/DEF:" + rebase_path("blacklist/test/blacklist_test_main_dll.def", + root_build_dir) ] +} + +shared_library("blacklist_test_dll_1") { + sources = [ + "blacklist/test/blacklist_test_dll_1.cc", + ] + ldflags = [ "/DEF:" + rebase_path("blacklist/test/blacklist_test_dll_1.def", + root_build_dir) ] +} + +shared_library("blacklist_test_dll_2") { + sources = [ + "blacklist/test/blacklist_test_dll_2.cc", + ] + ldflags = [ "/DEF:" + rebase_path("blacklist/test/blacklist_test_dll_2.def", + root_build_dir) ] +} + +shared_library("blacklist_test_dll_3") { + sources = [ + "blacklist/test/blacklist_test_dll_3.cc", + ] +}
diff --git a/chromecast/browser/service/cast_service_simple.cc b/chromecast/browser/service/cast_service_simple.cc index 36f8b64..9c7ca6d 100644 --- a/chromecast/browser/service/cast_service_simple.cc +++ b/chromecast/browser/service/cast_service_simple.cc
@@ -10,7 +10,6 @@ #include "content/public/browser/web_contents.h" #include "net/base/filename_util.h" #include "net/url_request/url_request_context_getter.h" -#include "url/gurl.h" namespace chromecast { @@ -54,6 +53,7 @@ } void CastServiceSimple::InitializeInternal() { + startup_url_ = GetStartupURL(); } void CastServiceSimple::FinalizeInternal() { @@ -67,8 +67,7 @@ web_contents_ = window_->CreateWebContents(initial_size, browser_context()); window_->CreateWindowTree(initial_size, web_contents_.get()); - web_contents_->GetController().LoadURL(GetStartupURL(), - content::Referrer(), + web_contents_->GetController().LoadURL(startup_url_, content::Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); }
diff --git a/chromecast/browser/service/cast_service_simple.h b/chromecast/browser/service/cast_service_simple.h index ebb2ed9..8ce5a13 100644 --- a/chromecast/browser/service/cast_service_simple.h +++ b/chromecast/browser/service/cast_service_simple.h
@@ -7,6 +7,7 @@ #include "base/memory/scoped_ptr.h" #include "chromecast/browser/service/cast_service.h" +#include "url/gurl.h" namespace content { class WebContents; @@ -32,6 +33,7 @@ private: scoped_ptr<CastContentWindow> window_; scoped_ptr<content::WebContents> web_contents_; + GURL startup_url_; DISALLOW_COPY_AND_ASSIGN(CastServiceSimple); };
diff --git a/chromecast/chromecast.gyp b/chromecast/chromecast.gyp index c9335f0..60de9bf 100644 --- a/chromecast/chromecast.gyp +++ b/chromecast/chromecast.gyp
@@ -6,6 +6,7 @@ 'variables': { 'android_support_v13_target%': '../third_party/android_tools/android_tools.gyp:android_support_v13_javalib', + 'cast_build_release': 'internal/build/cast_build_release', 'chromium_code': 1, 'chromecast_branding%': 'Chromium', 'disable_display%': 0, @@ -260,8 +261,12 @@ 'python', '<(version_py_path)', '-e', 'VERSION_FULL="<(version_full)"', - # Revision is taken from buildbot if available; otherwise, a dev string is used. - '-e', 'CAST_BUILD_REVISION="<!(echo ${CAST_BUILD_REVISION:="eng.${USER}.<!(date +%Y%m%d.%H%M%S)"})"', + # CAST_BUILD_INCREMENTAL is taken from buildbot if available; + # otherwise, a dev string is used. + '-e', 'CAST_BUILD_INCREMENTAL="<!(echo ${CAST_BUILD_INCREMENTAL:="<!(date +%Y%m%d.%H%M%S)"})"', + # CAST_BUILD_RELEASE is taken from cast_build_release file if exist; + # otherwise, a dev string is used. + '-e', 'CAST_BUILD_RELEASE="<!(if test -f <(cast_build_release); then cat <(cast_build_release); else echo eng.${USER}; fi)"', '-e', 'CAST_IS_DEBUG_BUILD=1 if "<(CONFIGURATION_NAME)" == "Debug" else 0', 'common/version.h.in', '<@(_outputs)',
diff --git a/chromecast/common/version.h.in b/chromecast/common/version.h.in index 628cb4c..cfc7d03 100644 --- a/chromecast/common/version.h.in +++ b/chromecast/common/version.h.in
@@ -8,7 +8,8 @@ #define CHROMECAST_COMMON_VERSION_INFO_H_ #define PRODUCT_VERSION "@VERSION_FULL@" -#define CAST_BUILD_REVISION "@CAST_BUILD_REVISION@" +#define CAST_BUILD_INCREMENTAL "@CAST_BUILD_INCREMENTAL@" +#define CAST_BUILD_REVISION "@CAST_BUILD_RELEASE@.@CAST_BUILD_INCREMENTAL@" #define CAST_IS_DEBUG_BUILD @CAST_IS_DEBUG_BUILD@ #endif // CHROMECAST_COMMON_VERSION_INFO_H_
diff --git a/chromecast/media/cma/filters/cma_renderer.cc b/chromecast/media/cma/filters/cma_renderer.cc index 600ec5b..799dd61 100644 --- a/chromecast/media/cma/filters/cma_renderer.cc +++ b/chromecast/media/cma/filters/cma_renderer.cc
@@ -62,12 +62,15 @@ CmaRenderer::~CmaRenderer() { DCHECK(thread_checker_.CalledOnValidThread()); - FireAllPendingCallbacks(); + if (!init_cb_.is_null()) + base::ResetAndReturn(&init_cb_).Run(::media::PIPELINE_ERROR_ABORT); + else if (!flush_cb_.is_null()) + base::ResetAndReturn(&flush_cb_).Run(); } void CmaRenderer::Initialize( ::media::DemuxerStreamProvider* demuxer_stream_provider, - const base::Closure& init_cb, + const ::media::PipelineStatusCB& init_cb, const ::media::StatisticsCB& statistics_cb, const ::media::BufferingStateCB& buffering_state_cb, const PaintCB& paint_cb, @@ -81,8 +84,8 @@ DCHECK(!ended_cb.is_null()); DCHECK(!error_cb.is_null()); DCHECK(!buffering_state_cb.is_null()); - DCHECK(demuxer_stream_provider_->GetStream(::media::DemuxerStream::AUDIO) || - demuxer_stream_provider_->GetStream(::media::DemuxerStream::VIDEO)); + DCHECK(demuxer_stream_provider->GetStream(::media::DemuxerStream::AUDIO) || + demuxer_stream_provider->GetStream(::media::DemuxerStream::VIDEO)); BeginStateTransition(); @@ -259,12 +262,16 @@ void CmaRenderer::OnAudioPipelineInitializeDone( ::media::PipelineStatus status) { DCHECK(thread_checker_.CalledOnValidThread()); + + // OnError() may be fired at any time, even before initialization is complete. + if (state_ == kError) + return; + DCHECK_EQ(state_, kUninitialized) << state_; DCHECK(!init_cb_.is_null()); - if (status != ::media::PIPELINE_OK) { has_audio_ = false; - OnError(status); + base::ResetAndReturn(&init_cb_).Run(status); return; } @@ -321,17 +328,21 @@ void CmaRenderer::OnVideoPipelineInitializeDone( ::media::PipelineStatus status) { DCHECK(thread_checker_.CalledOnValidThread()); + + // OnError() may be fired at any time, even before initialization is complete. + if (state_ == kError) + return; + DCHECK_EQ(state_, kUninitialized) << state_; DCHECK(!init_cb_.is_null()); - if (status != ::media::PIPELINE_OK) { has_video_ = false; - OnError(status); + base::ResetAndReturn(&init_cb_).Run(status); return; } CompleteStateTransition(kFlushed); - base::ResetAndReturn(&init_cb_).Run(); + base::ResetAndReturn(&init_cb_).Run(::media::PIPELINE_OK); } void CmaRenderer::OnEosReached(bool is_audio) { @@ -423,18 +434,18 @@ DCHECK_NE(::media::PIPELINE_OK, error) << "PIPELINE_OK isn't an error!"; LOG(ERROR) << "CMA error encountered: " << error; - // Pipeline will destroy |this| as the result of error. - if (state_ != kError) - error_cb_.Run(error); - + State old_state = state_; CompleteStateTransition(kError); - FireAllPendingCallbacks(); -} -void CmaRenderer::FireAllPendingCallbacks() { - DCHECK(thread_checker_.CalledOnValidThread()); - if (!init_cb_.is_null()) - base::ResetAndReturn(&init_cb_).Run(); + if (old_state != kError) { + if (!init_cb_.is_null()) { + base::ResetAndReturn(&init_cb_).Run(error); + return; + } + error_cb_.Run(error); + } + + // After OnError() returns, the pipeline may destroy |this|. if (!flush_cb_.is_null()) base::ResetAndReturn(&flush_cb_).Run(); }
diff --git a/chromecast/media/cma/filters/cma_renderer.h b/chromecast/media/cma/filters/cma_renderer.h index d1c83ac..33fc2b1 100644 --- a/chromecast/media/cma/filters/cma_renderer.h +++ b/chromecast/media/cma/filters/cma_renderer.h
@@ -40,7 +40,7 @@ // ::media::Renderer implementation: void Initialize( ::media::DemuxerStreamProvider* demuxer_stream_provider, - const base::Closure& init_cb, + const ::media::PipelineStatusCB& init_cb, const ::media::StatisticsCB& statistics_cb, const ::media::BufferingStateCB& buffering_state_cb, const PaintCB& paint_cb, @@ -86,8 +86,6 @@ void OnFlushDone(::media::PipelineStatus status); void OnError(::media::PipelineStatus status); - void FireAllPendingCallbacks(); - // Begin a state transition. // Return true if delayed because of a pending state transition. void BeginStateTransition(); @@ -104,7 +102,7 @@ // Set of callbacks. PaintCB paint_cb_; - base::Closure init_cb_; + ::media::PipelineStatusCB init_cb_; ::media::StatisticsCB statistics_cb_; base::Closure ended_cb_; ::media::PipelineStatusCB error_cb_;
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM index 0c44346..33b1151 100644 --- a/chromeos/CHROMEOS_LKGM +++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@ -6713.0.0 \ No newline at end of file +6725.0.0 \ No newline at end of file
diff --git a/chromeos/chromeos.gyp b/chromeos/chromeos.gyp index 34022a3..1e854892 100644 --- a/chromeos/chromeos.gyp +++ b/chromeos/chromeos.gyp
@@ -337,6 +337,8 @@ 'network/network_configuration_observer.h', 'network/network_connection_handler.cc', 'network/network_connection_handler.h', + 'network/network_connection_observer.cc', + 'network/network_connection_observer.h', 'network/network_device_handler.cc', 'network/network_device_handler.h', 'network/network_device_handler_impl.cc',
diff --git a/chromeos/dbus/shill_client_helper.cc b/chromeos/dbus/shill_client_helper.cc index c927180..6418015 100644 --- a/chromeos/dbus/shill_client_helper.cc +++ b/chromeos/dbus/shill_client_helper.cc
@@ -7,6 +7,7 @@ #include "base/bind.h" #include "base/callback_helpers.h" #include "base/values.h" +#include "chromeos/device_event_log.h" #include "dbus/message.h" #include "dbus/object_proxy.h" #include "dbus/values_util.h" @@ -211,8 +212,8 @@ } ShillClientHelper::~ShillClientHelper() { - LOG_IF(ERROR, observer_list_.might_have_observers()) - << "ShillClientHelper destroyed with active observers"; + if (observer_list_.might_have_observers()) + NET_LOG(ERROR) << "ShillClientHelper destroyed with active observers"; } void ShillClientHelper::SetReleasedCallback(ReleasedCallback callback) { @@ -394,34 +395,55 @@ error_callback)); } -// static -void ShillClientHelper::AppendValueDataAsVariant(dbus::MessageWriter* writer, - const base::Value& value) { +namespace { + +enum DictionaryType { DICTIONARY_TYPE_VARIANT, DICTIONARY_TYPE_STRING }; + +// Appends an a{ss} dictionary to |writer|. |dictionary| must only contain +// strings. +void AppendStringDictionary(const base::DictionaryValue& dictionary, + dbus::MessageWriter* writer) { + dbus::MessageWriter variant_writer(NULL); + writer->OpenVariant("a{ss}", &variant_writer); + dbus::MessageWriter array_writer(NULL); + variant_writer.OpenArray("{ss}", &array_writer); + for (base::DictionaryValue::Iterator it(dictionary); !it.IsAtEnd(); + it.Advance()) { + dbus::MessageWriter entry_writer(NULL); + array_writer.OpenDictEntry(&entry_writer); + entry_writer.AppendString(it.key()); + const base::Value& value = it.value(); + std::string value_string; + if (!value.GetAsString(&value_string)) + NET_LOG(ERROR) << "Dictionary value not a string: " << it.key(); + entry_writer.AppendString(value_string); + array_writer.CloseContainer(&entry_writer); + } + variant_writer.CloseContainer(&array_writer); + writer->CloseContainer(&variant_writer); +} + +// Implements AppendValueDataAsVariant. If |dictionary_type| is +// DICTIONARY_TYPE_VARIANT and |value| is a Dictionary then it will be written +// as type 'a{ss}'. Otherwise dictionaries are written as type a{sv}. (This is +// to support Cellular.APN which expects a string -> string dictionary). +void AppendValueDataAsVariantInternal(dbus::MessageWriter* writer, + const base::Value& value, + DictionaryType dictionary_type) { // Support basic types and string-to-string dictionary. switch (value.GetType()) { case base::Value::TYPE_DICTIONARY: { const base::DictionaryValue* dictionary = NULL; value.GetAsDictionary(&dictionary); - dbus::MessageWriter variant_writer(NULL); - writer->OpenVariant("a{ss}", &variant_writer); - dbus::MessageWriter array_writer(NULL); - variant_writer.OpenArray("{ss}", &array_writer); - for (base::DictionaryValue::Iterator it(*dictionary); - !it.IsAtEnd(); - it.Advance()) { - dbus::MessageWriter entry_writer(NULL); - array_writer.OpenDictEntry(&entry_writer); - entry_writer.AppendString(it.key()); - const base::Value& value = it.value(); - std::string value_string; - DLOG_IF(ERROR, value.GetType() != base::Value::TYPE_STRING) - << "Unexpected type " << value.GetType(); - value.GetAsString(&value_string); - entry_writer.AppendString(value_string); - array_writer.CloseContainer(&entry_writer); + if (dictionary_type == DICTIONARY_TYPE_STRING) { + AppendStringDictionary(*dictionary, writer); + } else { + dbus::MessageWriter variant_writer(NULL); + writer->OpenVariant("a{sv}", &variant_writer); + ShillClientHelper::AppendServicePropertiesDictionary(&variant_writer, + *dictionary); + writer->CloseContainer(&variant_writer); } - variant_writer.CloseContainer(&array_writer); - writer->CloseContainer(&variant_writer); break; } case base::Value::TYPE_LIST: { @@ -434,10 +456,9 @@ for (base::ListValue::const_iterator it = list->begin(); it != list->end(); ++it) { const base::Value& value = **it; - LOG_IF(ERROR, value.GetType() != base::Value::TYPE_STRING) - << "Unexpected type " << value.GetType(); std::string value_string; - value.GetAsString(&value_string); + if (!value.GetAsString(&value_string)) + NET_LOG(ERROR) << "List value not a string: " << value; array_writer.AppendString(value_string); } variant_writer.CloseContainer(&array_writer); @@ -451,9 +472,16 @@ dbus::AppendBasicTypeValueDataAsVariant(writer, value); break; default: - DLOG(ERROR) << "Unexpected type " << value.GetType(); + NET_LOG(ERROR) << "Unexpected value type: " << value.GetType(); } +} +} // namespace + +// static +void ShillClientHelper::AppendValueDataAsVariant(dbus::MessageWriter* writer, + const base::Value& value) { + AppendValueDataAsVariantInternal(writer, value, DICTIONARY_TYPE_VARIANT); } // static @@ -462,13 +490,19 @@ const base::DictionaryValue& dictionary) { dbus::MessageWriter array_writer(NULL); writer->OpenArray("{sv}", &array_writer); - for (base::DictionaryValue::Iterator it(dictionary); - !it.IsAtEnd(); + for (base::DictionaryValue::Iterator it(dictionary); !it.IsAtEnd(); it.Advance()) { dbus::MessageWriter entry_writer(NULL); array_writer.OpenDictEntry(&entry_writer); entry_writer.AppendString(it.key()); - ShillClientHelper::AppendValueDataAsVariant(&entry_writer, it.value()); + // Shill expects Cellular.APN to be a string dictionary, a{ss}. All other + // properties use a varient dictionary, a{sv}. TODO(stevenjb): Remove this + // hack if/when we change Shill to accept a{sv} for Cellular.APN. + DictionaryType dictionary_type = (it.key() == shill::kCellularApnProperty) + ? DICTIONARY_TYPE_STRING + : DICTIONARY_TYPE_VARIANT; + AppendValueDataAsVariantInternal(&entry_writer, it.value(), + dictionary_type); array_writer.CloseContainer(&entry_writer); } writer->CloseContainer(&array_writer); @@ -487,8 +521,8 @@ void ShillClientHelper::OnSignalConnected(const std::string& interface, const std::string& signal, bool success) { - LOG_IF(ERROR, !success) << "Connect to " << interface << " " << signal - << " failed."; + if (!success) + NET_LOG(ERROR) << "Connect to " << interface << " " << signal << " failed."; } void ShillClientHelper::OnPropertyChanged(dbus::Signal* signal) {
diff --git a/chromeos/dbus/shill_client_helper.h b/chromeos/dbus/shill_client_helper.h index a52fc22..e2795e4 100644 --- a/chromeos/dbus/shill_client_helper.h +++ b/chromeos/dbus/shill_client_helper.h
@@ -141,15 +141,16 @@ const dbus::ObjectProxy* object_proxy() const { return proxy_; } - // Appends the value (basic types and string-to-string dictionary) to the - // writer as a variant. + // Appends the value to the writer as a variant. If |value| is a Dictionary it + // will be written as a string -> varient dictionary, a{sv}. If |value| is a + // List then it must be a List of String values and is writen as type 'as'. static void AppendValueDataAsVariant(dbus::MessageWriter* writer, const base::Value& value); - // Appends a string-to-variant dictionary to the writer. - static void AppendServicePropertiesDictionary( - dbus::MessageWriter* writer, - const base::DictionaryValue& dictionary); + // Appends a string-to-variant dictionary to the writer as an '{sv}' array. + // Each value is written using AppendValueDataAsVariant. + static void AppendServicePropertiesDictionary(dbus::MessageWriter* writer, + const base::DictionaryValue&); protected: // Reference / Ownership management. If the number of active refs (observers
diff --git a/chromeos/network/auto_connect_handler.cc b/chromeos/network/auto_connect_handler.cc index a968ce43..9a84673 100644 --- a/chromeos/network/auto_connect_handler.cc +++ b/chromeos/network/auto_connect_handler.cc
@@ -16,6 +16,7 @@ #include "chromeos/dbus/shill_service_client.h" #include "chromeos/network/device_state.h" #include "chromeos/network/managed_network_configuration_handler.h" +#include "chromeos/network/network_connection_handler.h" #include "chromeos/network/network_event_log.h" #include "chromeos/network/network_state.h" #include "chromeos/network/network_type_pattern.h"
diff --git a/chromeos/network/auto_connect_handler.h b/chromeos/network/auto_connect_handler.h index 9977107..26444dc 100644 --- a/chromeos/network/auto_connect_handler.h +++ b/chromeos/network/auto_connect_handler.h
@@ -12,26 +12,25 @@ #include "chromeos/chromeos_export.h" #include "chromeos/login/login_state.h" #include "chromeos/network/client_cert_resolver.h" -#include "chromeos/network/network_connection_handler.h" +#include "chromeos/network/network_connection_observer.h" #include "chromeos/network/network_handler.h" #include "chromeos/network/network_policy_observer.h" #include "chromeos/network/network_state_handler_observer.h" namespace chromeos { -class CHROMEOS_EXPORT AutoConnectHandler - : public LoginState::Observer, - public NetworkPolicyObserver, - public NetworkConnectionHandler::Observer, - public NetworkStateHandlerObserver, - public ClientCertResolver::Observer { +class CHROMEOS_EXPORT AutoConnectHandler : public LoginState::Observer, + public NetworkPolicyObserver, + public NetworkConnectionObserver, + public NetworkStateHandlerObserver, + public ClientCertResolver::Observer { public: ~AutoConnectHandler() override; // LoginState::Observer void LoggedInStateChanged() override; - // NetworkConnectionHandler::Observer + // NetworkConnectionObserver void ConnectToNetworkRequested(const std::string& service_path) override; // NetworkPolicyObserver
diff --git a/chromeos/network/network_connection_handler.cc b/chromeos/network/network_connection_handler.cc index 5fbdd79..af9f26a 100644 --- a/chromeos/network/network_connection_handler.cc +++ b/chromeos/network/network_connection_handler.cc
@@ -32,14 +32,6 @@ namespace { -void InvokeErrorCallback(const std::string& service_path, - const network_handler::ErrorCallback& error_callback, - const std::string& error_name) { - NET_LOG_ERROR("Connect Error: " + error_name, service_path); - network_handler::RunErrorCallback( - error_callback, service_path, error_name, ""); -} - bool IsAuthenticationError(const std::string& error) { return (error == shill::kErrorBadWEPKey || error == shill::kErrorPppAuthFailed || @@ -108,15 +100,16 @@ const char NetworkConnectionHandler::kErrorNotConnected[] = "not-connected"; const char NetworkConnectionHandler::kErrorPassphraseRequired[] = "passphrase-required"; -const char NetworkConnectionHandler::kErrorActivationRequired[] = - "activation-required"; +const char NetworkConnectionHandler::kErrorBadPassphrase[] = "bad-passphrase"; const char NetworkConnectionHandler::kErrorCertificateRequired[] = "certificate-required"; const char NetworkConnectionHandler::kErrorConfigurationRequired[] = "configuration-required"; const char NetworkConnectionHandler::kErrorAuthenticationRequired[] = "authentication-required"; -const char NetworkConnectionHandler::kErrorShillError[] = "shill-error"; +const char NetworkConnectionHandler::kErrorConnectFailed[] = "connect-failed"; +const char NetworkConnectionHandler::kErrorDisconnectFailed[] = + "disconnect-failed"; const char NetworkConnectionHandler::kErrorConfigureFailed[] = "configure-failed"; const char NetworkConnectionHandler::kErrorConnectCanceled[] = @@ -198,11 +191,13 @@ LoggedInStateChanged(); } -void NetworkConnectionHandler::AddObserver(Observer* observer) { +void NetworkConnectionHandler::AddObserver( + NetworkConnectionObserver* observer) { observers_.AddObserver(observer); } -void NetworkConnectionHandler::RemoveObserver(Observer* observer) { +void NetworkConnectionHandler::RemoveObserver( + NetworkConnectionObserver* observer) { observers_.RemoveObserver(observer); } @@ -230,14 +225,14 @@ const network_handler::ErrorCallback& error_callback, bool check_error_state) { NET_LOG_USER("ConnectToNetwork", service_path); - FOR_EACH_OBSERVER(Observer, observers_, + FOR_EACH_OBSERVER(NetworkConnectionObserver, observers_, ConnectToNetworkRequested(service_path)); // Clear any existing queued connect request. queued_connect_.reset(); if (HasConnectingNetwork(service_path)) { NET_LOG_USER("Connect Request While Pending", service_path); - InvokeErrorCallback(service_path, error_callback, kErrorConnecting); + InvokeConnectErrorCallback(service_path, error_callback, kErrorConnecting); return; } @@ -251,23 +246,25 @@ if (network) { // For existing networks, perform some immediate consistency checks. if (network->IsConnectedState()) { - InvokeErrorCallback(service_path, error_callback, kErrorConnected); + InvokeConnectErrorCallback(service_path, error_callback, kErrorConnected); return; } if (network->IsConnectingState()) { - InvokeErrorCallback(service_path, error_callback, kErrorConnecting); + InvokeConnectErrorCallback(service_path, error_callback, + kErrorConnecting); return; } if (check_error_state) { const std::string& error = network->last_error(); if (error == shill::kErrorBadPassphrase) { - InvokeErrorCallback(service_path, error_callback, error); + InvokeConnectErrorCallback(service_path, error_callback, + kErrorBadPassphrase); return; } if (IsAuthenticationError(error)) { - InvokeErrorCallback( - service_path, error_callback, kErrorAuthenticationRequired); + InvokeConnectErrorCallback(service_path, error_callback, + kErrorAuthenticationRequired); return; } } @@ -309,14 +306,21 @@ const base::Closure& success_callback, const network_handler::ErrorCallback& error_callback) { NET_LOG_USER("DisconnectNetwork", service_path); + FOR_EACH_OBSERVER(NetworkConnectionObserver, observers_, + DiconnectRequested(service_path)); + const NetworkState* network = network_state_handler_->GetNetworkState(service_path); if (!network) { - InvokeErrorCallback(service_path, error_callback, kErrorNotFound); + NET_LOG_ERROR("Disconnect Error: Not Found", service_path); + network_handler::RunErrorCallback(error_callback, service_path, + kErrorNotFound, ""); return; } if (!network->IsConnectedState() && !network->IsConnectingState()) { - InvokeErrorCallback(service_path, error_callback, kErrorNotConnected); + NET_LOG_ERROR("Disconnect Error: Not Connected", service_path); + network_handler::RunErrorCallback(error_callback, service_path, + kErrorNotConnected, ""); return; } pending_requests_.erase(service_path); @@ -535,9 +539,8 @@ base::TimeDelta dtime = base::TimeTicks::Now() - logged_in_time_; if (dtime > base::TimeDelta::FromSeconds(kMaxCertLoadTimeSeconds)) { NET_LOG_ERROR("Certificate load timeout", service_path); - InvokeErrorCallback(service_path, - request->error_callback, - kErrorCertLoadTimeout); + InvokeConnectErrorCallback(service_path, request->error_callback, + kErrorCertLoadTimeout); return; } @@ -566,9 +569,9 @@ return; // Otherwise, notify the user. NET_LOG_ERROR("Certificate load timeout", queued_connect_->service_path); - InvokeErrorCallback(queued_connect_->service_path, - queued_connect_->error_callback, - kErrorCertLoadTimeout); + InvokeConnectErrorCallback(queued_connect_->service_path, + queued_connect_->error_callback, + kErrorCertLoadTimeout); queued_connect_.reset(); } @@ -611,8 +614,8 @@ } network_handler::ErrorCallback error_callback = request->error_callback; pending_requests_.erase(service_path); - if (!error_callback.is_null()) - error_callback.Run(kErrorConfigureFailed, error_data.Pass()); + InvokeConnectErrorCallback(service_path, error_callback, + kErrorConfigureFailed); } void NetworkConnectionHandler::HandleShillConnectSuccess( @@ -644,9 +647,17 @@ } network_handler::ErrorCallback error_callback = request->error_callback; pending_requests_.erase(service_path); - network_handler::ShillErrorCallbackFunction( - shill::kErrorConnectFailed, service_path, error_callback, - dbus_error_name, dbus_error_message); + std::string error; + if (dbus_error_name == shill::kErrorResultAlreadyConnected) { + error = kErrorConnected; + } else if (dbus_error_name == shill::kErrorResultInProgress) { + error = kErrorConnecting; + } else { + NET_LOG_ERROR("Connect Failure, Shill error: " + dbus_error_name, + service_path); + error = kErrorConnectFailed; + } + InvokeConnectErrorCallback(service_path, error_callback, error); } void NetworkConnectionHandler::CheckPendingRequest( @@ -665,7 +676,6 @@ return; } if (network->IsConnectedState()) { - NET_LOG_EVENT("Connect Request Succeeded", service_path); if (!request->profile_path.empty()) { // If a profile path was specified, set it on a successful connection. configuration_handler_->SetNetworkProfile( @@ -675,8 +685,8 @@ base::Bind(&base::DoNothing), chromeos::network_handler::ErrorCallback()); } - if (!request->success_callback.is_null()) - request->success_callback.Run(); + InvokeConnectSuccessCallback(request->service_path, + request->success_callback); pending_requests_.erase(service_path); return; } @@ -693,7 +703,7 @@ // Another connect request canceled this one. error_name = kErrorConnectCanceled; } else { - error_name = shill::kErrorConnectFailed; + error_name = kErrorConnectFailed; if (network->connection_state() != shill::kStateFailure) { NET_LOG_ERROR("Unexpected State: " + network->connection_state(), service_path); @@ -702,11 +712,7 @@ network_handler::ErrorCallback error_callback = request->error_callback; pending_requests_.erase(service_path); - if (error_callback.is_null()) { - NET_LOG_ERROR("Connect Error, no callback: " + error_name, service_path); - return; - } - InvokeErrorCallback(service_path, error_callback, error_name); + InvokeConnectErrorCallback(service_path, error_callback, error_name); } void NetworkConnectionHandler::CheckAllPendingRequests() { @@ -716,6 +722,18 @@ } } +// Connect callbacks + +void NetworkConnectionHandler::InvokeConnectSuccessCallback( + const std::string& service_path, + const base::Closure& success_callback) { + NET_LOG_EVENT("Connect Request Succeeded", service_path); + if (!success_callback.is_null()) + success_callback.Run(); + FOR_EACH_OBSERVER(NetworkConnectionObserver, observers_, + ConnectSucceeded(service_path)); +} + void NetworkConnectionHandler::ErrorCallbackForPendingRequest( const std::string& service_path, const std::string& error_name) { @@ -728,7 +746,18 @@ // Remove the entry before invoking the callback in case it triggers a retry. network_handler::ErrorCallback error_callback = request->error_callback; pending_requests_.erase(service_path); - InvokeErrorCallback(service_path, error_callback, error_name); + InvokeConnectErrorCallback(service_path, error_callback, error_name); +} + +void NetworkConnectionHandler::InvokeConnectErrorCallback( + const std::string& service_path, + const network_handler::ErrorCallback& error_callback, + const std::string& error_name) { + NET_LOG_ERROR("Connect Failure: " + error_name, service_path); + network_handler::RunErrorCallback(error_callback, service_path, error_name, + ""); + FOR_EACH_OBSERVER(NetworkConnectionObserver, observers_, + ConnectFailed(service_path, error_name)); } // Disconnect @@ -743,7 +772,7 @@ base::Bind(&NetworkConnectionHandler::HandleShillDisconnectSuccess, AsWeakPtr(), service_path, success_callback), base::Bind(&network_handler::ShillErrorCallbackFunction, - kErrorShillError, service_path, error_callback)); + kErrorDisconnectFailed, service_path, error_callback)); } void NetworkConnectionHandler::HandleShillDisconnectSuccess(
diff --git a/chromeos/network/network_connection_handler.h b/chromeos/network/network_connection_handler.h index 7cdb19e..aef25b94 100644 --- a/chromeos/network/network_connection_handler.h +++ b/chromeos/network/network_connection_handler.h
@@ -19,6 +19,7 @@ #include "chromeos/chromeos_export.h" #include "chromeos/dbus/dbus_method_call_status.h" #include "chromeos/login/login_state.h" +#include "chromeos/network/network_connection_observer.h" #include "chromeos/network/network_handler.h" #include "chromeos/network/network_handler_callbacks.h" #include "chromeos/network/network_state_handler_observer.h" @@ -49,19 +50,6 @@ public NetworkStateHandlerObserver, public base::SupportsWeakPtr<NetworkConnectionHandler> { public: - class Observer { - public: - // Called if a connection to network |service_path| was requested, by - // calling ConnectToNetwork. - virtual void ConnectToNetworkRequested(const std::string& service_path) = 0; - - protected: - virtual ~Observer() {} - - private: - DISALLOW_ASSIGN(Observer); - }; - // Constants for |error_name| from |error_callback| for Connect. // No network matching |service_path| is found (hidden networks must be @@ -77,7 +65,8 @@ // The passphrase is missing or invalid. static const char kErrorPassphraseRequired[]; - static const char kErrorActivationRequired[]; + // The passphrase is incorrect. + static const char kErrorBadPassphrase[]; // The network requires a cert and none exists. static const char kErrorCertificateRequired[]; @@ -92,8 +81,11 @@ // Configuration failed during the configure stage of the connect flow. static const char kErrorConfigureFailed[]; - // For Disconnect or Activate, an unexpected DBus or Shill error occurred. - static const char kErrorShillError[]; + // An unexpected DBus or Shill error occurred while connecting. + static const char kErrorConnectFailed[]; + + // An unexpected DBus or Shill error occurred while disconnecting. + static const char kErrorDisconnectFailed[]; // A new network connect request canceled this one. static const char kErrorConnectCanceled[]; @@ -106,15 +98,13 @@ ~NetworkConnectionHandler() override; - void AddObserver(Observer* observer); - void RemoveObserver(Observer* observer); + void AddObserver(NetworkConnectionObserver* observer); + void RemoveObserver(NetworkConnectionObserver* observer); // ConnectToNetwork() will start an asynchronous connection attempt. // On success, |success_callback| will be called. // On failure, |error_callback| will be called with |error_name| one of the - // constants defined above, or shill::kErrorConnectFailed or - // shill::kErrorBadPassphrase if the Shill Error property (from a - // previous connect attempt) was set to one of those. + // constants defined above. // |error_message| will contain an additional error string for debugging. // If |check_error_state| is true, the current state of the network is // checked for errors, otherwise current state is ignored (e.g. for recently @@ -129,7 +119,7 @@ // On failure, |error_callback| will be called with |error_name| one of: // kErrorNotFound if no network matching |service_path| is found. // kErrorNotConnected if not connected to the network. - // kErrorShillError if a DBus or Shill error occurred. + // kErrorDisconnectFailed if a DBus or Shill error occurred. // |error_message| will contain and additional error string for debugging. void DisconnectNetwork(const std::string& service_path, const base::Closure& success_callback, @@ -206,9 +196,22 @@ void CheckPendingRequest(const std::string service_path); void CheckAllPendingRequests(); + // Notify caller and observers that the connect request succeeded. + void InvokeConnectSuccessCallback(const std::string& service_path, + const base::Closure& success_callback); + + // Look up the ConnectRequest for |service_path| and call + // InvokeConnectErrorCallback. void ErrorCallbackForPendingRequest(const std::string& service_path, const std::string& error_name); + // Notify caller and observers that the connect request failed. + // |error_name| will be one of the kError* messages defined above. + void InvokeConnectErrorCallback( + const std::string& service_path, + const network_handler::ErrorCallback& error_callback, + const std::string& error_name); + // Calls Shill.Manager.Disconnect asynchronously. void CallShillDisconnect( const std::string& service_path, @@ -219,7 +222,7 @@ void HandleShillDisconnectSuccess(const std::string& service_path, const base::Closure& success_callback); - ObserverList<Observer> observers_; + ObserverList<NetworkConnectionObserver> observers_; // Local references to the associated handler instances. CertLoader* cert_loader_;
diff --git a/chromeos/network/network_connection_handler_unittest.cc b/chromeos/network/network_connection_handler_unittest.cc index ab4b00c3..8e059c91 100644 --- a/chromeos/network/network_connection_handler_unittest.cc +++ b/chromeos/network/network_connection_handler_unittest.cc
@@ -4,6 +4,9 @@ #include "chromeos/network/network_connection_handler.h" +#include <map> +#include <set> + #include "base/bind.h" #include "base/callback.h" #include "base/files/file_util.h" @@ -20,6 +23,7 @@ #include "chromeos/dbus/shill_service_client.h" #include "chromeos/network/managed_network_configuration_handler_impl.h" #include "chromeos/network/network_configuration_handler.h" +#include "chromeos/network/network_connection_observer.h" #include "chromeos/network/network_profile_handler.h" #include "chromeos/network/network_state_handler.h" #include "chromeos/network/onc/onc_utils.h" @@ -34,6 +38,8 @@ #include "testing/gtest/include/gtest/gtest.h" #include "third_party/cros_system_api/dbus/service_constants.h" +namespace chromeos { + namespace { const char* kSuccessResult = "success"; @@ -46,9 +52,48 @@ const std::string& error_message) { } -} // namespace +class TestNetworkConnectionObserver : public NetworkConnectionObserver { + public: + TestNetworkConnectionObserver() {} + ~TestNetworkConnectionObserver() override {} -namespace chromeos { + // NetworkConnectionObserver + void ConnectToNetworkRequested(const std::string& service_path) override { + requests_.insert(service_path); + } + + void ConnectSucceeded(const std::string& service_path) override { + results_[service_path] = kSuccessResult; + } + + void ConnectFailed(const std::string& service_path, + const std::string& error_name) override { + results_[service_path] = error_name; + } + + void DiconnectRequested(const std::string& service_path) override { + requests_.insert(service_path); + } + + bool GetRequested(const std::string& service_path) { + return requests_.count(service_path) != 0; + } + + std::string GetResult(const std::string& service_path) { + auto iter = results_.find(service_path); + if (iter == results_.end()) + return ""; + return iter->second; + } + + private: + std::set<std::string> requests_; + std::map<std::string, std::string> results_; + + DISALLOW_COPY_AND_ASSIGN(TestNetworkConnectionObserver); +}; + +} // namespace class NetworkConnectionHandlerTest : public testing::Test { public: @@ -106,6 +151,9 @@ network_connection_handler_->Init(network_state_handler_.get(), network_config_handler_.get(), managed_config_handler_.get()); + network_connection_observer_.reset(new TestNetworkConnectionObserver); + network_connection_handler_->AddObserver( + network_connection_observer_.get()); base::RunLoop().RunUntilIdle(); } @@ -113,6 +161,9 @@ void TearDown() override { managed_config_handler_.reset(); network_profile_handler_.reset(); + network_connection_handler_->RemoveObserver( + network_connection_observer_.get()); + network_connection_observer_.reset(); network_connection_handler_.reset(); network_config_handler_.reset(); network_state_handler_.reset(); @@ -248,6 +299,7 @@ scoped_ptr<NetworkStateHandler> network_state_handler_; scoped_ptr<NetworkConfigurationHandler> network_config_handler_; scoped_ptr<NetworkConnectionHandler> network_connection_handler_; + scoped_ptr<TestNetworkConnectionObserver> network_connection_observer_; scoped_ptr<ManagedNetworkConfigurationHandlerImpl> managed_config_handler_; scoped_ptr<NetworkProfileHandler> network_profile_handler_; ShillManagerClient::TestInterface* test_manager_client_; @@ -263,6 +315,12 @@ namespace { +const char* kNoNetwork = "no-network"; +const char* kWifi0 = "wifi0"; +const char* kWifi1 = "wifi1"; +const char* kWifi2 = "wifi2"; +const char* kWifi3 = "wifi3"; + const char* kConfigConnectable = "{ \"GUID\": \"wifi0\", \"Type\": \"wifi\", \"State\": \"idle\", " " \"Connectable\": true }"; @@ -278,30 +336,45 @@ TEST_F(NetworkConnectionHandlerTest, NetworkConnectionHandlerConnectSuccess) { EXPECT_TRUE(Configure(kConfigConnectable)); - Connect("wifi0"); + Connect(kWifi0); EXPECT_EQ(kSuccessResult, GetResultAndReset()); EXPECT_EQ(shill::kStateOnline, - GetServiceStringProperty("wifi0", shill::kStateProperty)); + GetServiceStringProperty(kWifi0, shill::kStateProperty)); + // Observer expectations + EXPECT_TRUE(network_connection_observer_->GetRequested(kWifi0)); + EXPECT_EQ(kSuccessResult, network_connection_observer_->GetResult(kWifi0)); } // Handles basic failure cases. TEST_F(NetworkConnectionHandlerTest, NetworkConnectionHandlerConnectFailure) { - Connect("no-network"); + Connect(kNoNetwork); EXPECT_EQ(NetworkConnectionHandler::kErrorConfigureFailed, GetResultAndReset()); + EXPECT_TRUE(network_connection_observer_->GetRequested(kNoNetwork)); + EXPECT_EQ(NetworkConnectionHandler::kErrorConfigureFailed, + network_connection_observer_->GetResult(kNoNetwork)); EXPECT_TRUE(Configure(kConfigConnected)); - Connect("wifi1"); + Connect(kWifi1); EXPECT_EQ(NetworkConnectionHandler::kErrorConnected, GetResultAndReset()); + EXPECT_TRUE(network_connection_observer_->GetRequested(kWifi1)); + EXPECT_EQ(NetworkConnectionHandler::kErrorConnected, + network_connection_observer_->GetResult(kWifi1)); EXPECT_TRUE(Configure(kConfigConnecting)); - Connect("wifi2"); + Connect(kWifi2); EXPECT_EQ(NetworkConnectionHandler::kErrorConnecting, GetResultAndReset()); + EXPECT_TRUE(network_connection_observer_->GetRequested(kWifi2)); + EXPECT_EQ(NetworkConnectionHandler::kErrorConnecting, + network_connection_observer_->GetResult(kWifi2)); EXPECT_TRUE(Configure(kConfigRequiresPassphrase)); - Connect("wifi3"); + Connect(kWifi3); EXPECT_EQ(NetworkConnectionHandler::kErrorPassphraseRequired, GetResultAndReset()); + EXPECT_TRUE(network_connection_observer_->GetRequested(kWifi3)); + EXPECT_EQ(NetworkConnectionHandler::kErrorPassphraseRequired, + network_connection_observer_->GetResult(kWifi3)); } namespace { @@ -382,18 +455,19 @@ TEST_F(NetworkConnectionHandlerTest, NetworkConnectionHandlerDisconnectSuccess) { EXPECT_TRUE(Configure(kConfigConnected)); - Disconnect("wifi1"); + Disconnect(kWifi1); + EXPECT_TRUE(network_connection_observer_->GetRequested(kWifi1)); EXPECT_EQ(kSuccessResult, GetResultAndReset()); } TEST_F(NetworkConnectionHandlerTest, NetworkConnectionHandlerDisconnectFailure) { - Connect("no-network"); + Connect(kNoNetwork); EXPECT_EQ(NetworkConnectionHandler::kErrorConfigureFailed, GetResultAndReset()); EXPECT_TRUE(Configure(kConfigConnectable)); - Disconnect("wifi0"); + Disconnect(kWifi0); EXPECT_EQ(NetworkConnectionHandler::kErrorNotConnected, GetResultAndReset()); }
diff --git a/chromeos/network/network_connection_observer.cc b/chromeos/network/network_connection_observer.cc new file mode 100644 index 0000000..4c4f5ae --- /dev/null +++ b/chromeos/network/network_connection_observer.cc
@@ -0,0 +1,31 @@ +// 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. + +#include "chromeos/network/network_connection_observer.h" + +namespace chromeos { + +NetworkConnectionObserver::NetworkConnectionObserver() { +} + +void NetworkConnectionObserver::ConnectToNetworkRequested( + const std::string& service_path) { +} + +void NetworkConnectionObserver::ConnectSucceeded( + const std::string& service_path) { +} + +void NetworkConnectionObserver::ConnectFailed(const std::string& service_path, + const std::string& error_name) { +} + +void NetworkConnectionObserver::DiconnectRequested( + const std::string& service_path) { +} + +NetworkConnectionObserver::~NetworkConnectionObserver() { +} + +} // namespace chromeos
diff --git a/chromeos/network/network_connection_observer.h b/chromeos/network/network_connection_observer.h new file mode 100644 index 0000000..d7aae7c2 --- /dev/null +++ b/chromeos/network/network_connection_observer.h
@@ -0,0 +1,47 @@ +// 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 CHROMEOS_NETWORK_NETWORK_CONNECTION_OBSERVER_H_ +#define CHROMEOS_NETWORK_NETWORK_CONNECTION_OBSERVER_H_ + +#include <string> + +#include "base/macros.h" +#include "chromeos/chromeos_export.h" + +namespace chromeos { + +// Observer class for network connection events. +class CHROMEOS_EXPORT NetworkConnectionObserver { + public: + NetworkConnectionObserver(); + + // Called when a connection to network |service_path| is requested by + // calling NetworkConnectionHandler::ConnectToNetwork. + virtual void ConnectToNetworkRequested(const std::string& service_path); + + // Called when a connection request succeeds. + virtual void ConnectSucceeded(const std::string& service_path); + + // Called when a connection request fails. Valid error names are defined in + // NetworkConnectionHandler. + virtual void ConnectFailed(const std::string& service_path, + const std::string& error_name); + + // Called when a disconnect to network |service_path| is requested by + // calling NetworkConnectionHandler::DisconnectNetwork. Success or failure + // for disconnect is not tracked here, observe NetworkStateHandler for state + // changes instead. + virtual void DiconnectRequested(const std::string& service_path); + + protected: + virtual ~NetworkConnectionObserver(); + + private: + DISALLOW_COPY_AND_ASSIGN(NetworkConnectionObserver); +}; + +} // namespace chromeos + +#endif // CHROMEOS_NETWORK_NETWORK_CONNECTION_OBSERVER_H_
diff --git a/chromeos/network/onc/onc_translator_shill_to_onc.cc b/chromeos/network/onc/onc_translator_shill_to_onc.cc index 4360d25f..f497421 100644 --- a/chromeos/network/onc/onc_translator_shill_to_onc.cc +++ b/chromeos/network/onc/onc_translator_shill_to_onc.cc
@@ -318,7 +318,7 @@ ::onc::wifi::kSecurity); bool unknown_encoding = true; std::string ssid = shill_property_util::GetSSIDFromProperties( - *shill_dictionary_, &unknown_encoding); + *shill_dictionary_, false /* verbose_logging */, &unknown_encoding); if (!unknown_encoding && !ssid.empty()) onc_object_->SetStringWithoutPathExpansion(::onc::wifi::kSSID, ssid);
diff --git a/chromeos/network/shill_property_util.cc b/chromeos/network/shill_property_util.cc index 75a94f7..7557dc3 100644 --- a/chromeos/network/shill_property_util.cc +++ b/chromeos/network/shill_property_util.cc
@@ -12,7 +12,7 @@ #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversion_utils.h" #include "base/values.h" -#include "chromeos/network/network_event_log.h" +#include "chromeos/device_event_log.h" #include "chromeos/network/network_ui_data.h" #include "chromeos/network/onc/onc_utils.h" #include "third_party/cros_system_api/dbus/service_constants.h" @@ -65,12 +65,10 @@ } std::string GetSSIDFromProperties(const base::DictionaryValue& properties, + bool verbose_logging, bool* unknown_encoding) { - bool verbose_logging = false; - if (unknown_encoding) { + if (unknown_encoding) *unknown_encoding = false; - verbose_logging = true; - } // Get name for debugging. std::string name; @@ -80,8 +78,9 @@ properties.GetStringWithoutPathExpansion(shill::kWifiHexSsid, &hex_ssid); if (hex_ssid.empty()) { + // Note: use VLOG here to avoid spamming the event log. if (verbose_logging) - NET_LOG_DEBUG("GetSSIDFromProperties: No HexSSID set.", name); + NET_LOG(DEBUG) << "GetSSIDFromProperties: No HexSSID set: " << name; return std::string(); } @@ -90,13 +89,12 @@ if (base::HexStringToBytes(hex_ssid, &raw_ssid_bytes)) { ssid = std::string(raw_ssid_bytes.begin(), raw_ssid_bytes.end()); if (verbose_logging) { - NET_LOG_DEBUG(base::StringPrintf("GetSSIDFromProperties: %s, SSID: %s", - hex_ssid.c_str(), ssid.c_str()), name); + NET_LOG(DEBUG) << "GetSSIDFromProperties: " << name + << " HexSsid=" << hex_ssid << " SSID=" << ssid; } } else { - NET_LOG_ERROR( - base::StringPrintf("GetSSIDFromProperties: Error processing: %s", - hex_ssid.c_str()), name); + NET_LOG(ERROR) << "GetSSIDFromProperties: " << name + << " Error processing HexSsid: " << hex_ssid; return std::string(); } @@ -117,9 +115,9 @@ base::ConvertToUtf8AndNormalize(ssid, encoding, &utf8_ssid)) { if (utf8_ssid != ssid) { if (verbose_logging) { - NET_LOG_DEBUG( - base::StringPrintf("GetSSIDFromProperties: Encoding=%s: %s", - encoding.c_str(), utf8_ssid.c_str()), name); + NET_LOG(DEBUG) << "GetSSIDFromProperties: " << name + << " Encoding=" << encoding << " SSID=" << ssid + << " UTF8 SSID=" << utf8_ssid; } } return utf8_ssid; @@ -128,9 +126,8 @@ if (unknown_encoding) *unknown_encoding = true; if (verbose_logging) { - NET_LOG_DEBUG( - base::StringPrintf("GetSSIDFromProperties: Unrecognized Encoding=%s", - encoding.c_str()), name); + NET_LOG(DEBUG) << "GetSSIDFromProperties: " << name + << " Unrecognized Encoding=" << encoding; } return ssid; } @@ -158,25 +155,26 @@ std::string validated_name = ValidateUTF8(name); if (validated_name != name) { - NET_LOG_DEBUG("GetNameFromProperties", - base::StringPrintf("Validated name %s: UTF8: %s", - service_path.c_str(), - validated_name.c_str())); + NET_LOG(DEBUG) << "GetNameFromProperties: " << service_path + << " Validated name=" << validated_name << " name=" << name; } std::string type; properties.GetStringWithoutPathExpansion(shill::kTypeProperty, &type); if (type.empty()) { - NET_LOG_ERROR("GetNameFromProperties: No type", service_path); + NET_LOG(ERROR) << "GetNameFromProperties: " << service_path << " No type."; return validated_name; } if (!NetworkTypePattern::WiFi().MatchesType(type)) return validated_name; bool unknown_ssid_encoding = false; - std::string ssid = GetSSIDFromProperties(properties, &unknown_ssid_encoding); - if (ssid.empty()) - NET_LOG_ERROR("GetNameFromProperties", "No SSID set: " + service_path); + std::string ssid = GetSSIDFromProperties( + properties, true /* verbose_logging */, &unknown_ssid_encoding); + if (ssid.empty()) { + NET_LOG(ERROR) << "GetNameFromProperties: " << service_path + << " No SSID set"; + } // Use |validated_name| if |ssid| is empty. // And if the encoding of the SSID is unknown, use |ssid|, which contains raw @@ -185,11 +183,8 @@ return validated_name; if (ssid != validated_name) { - NET_LOG_DEBUG("GetNameFromProperties", - base::StringPrintf("%s: SSID: %s, Name: %s", - service_path.c_str(), - ssid.c_str(), - validated_name.c_str())); + NET_LOG(DEBUG) << "GetNameFromProperties: " << service_path + << " SSID=" << ssid << " Validated name=" << validated_name; } return ssid; } @@ -265,8 +260,8 @@ const base::DictionaryValue* provider_properties = NULL; if (!service_properties.GetDictionaryWithoutPathExpansion( shill::kProviderProperty, &provider_properties)) { - NET_LOG_ERROR("Missing VPN provider dict", - GetNetworkIdFromProperties(service_properties)); + NET_LOG(ERROR) << "Missing VPN provider dict: " + << GetNetworkIdFromProperties(service_properties); } provider_properties->GetStringWithoutPathExpansion(shill::kTypeProperty, &vpn_provider_type); @@ -293,8 +288,8 @@ success = false; } if (!success) { - NET_LOG_ERROR("Missing required properties", - GetNetworkIdFromProperties(service_properties)); + NET_LOG(ERROR) << "Missing required properties: " + << GetNetworkIdFromProperties(service_properties); } return success; }
diff --git a/chromeos/network/shill_property_util.h b/chromeos/network/shill_property_util.h index 5694e793..3637c6a 100644 --- a/chromeos/network/shill_property_util.h +++ b/chromeos/network/shill_property_util.h
@@ -25,10 +25,13 @@ CHROMEOS_EXPORT void SetSSID(const std::string ssid, base::DictionaryValue* properties); -// Returns the SSID from |properties| in UTF-8 encoding. If |unknown_encoding| -// is not NULL, it is set to whether the SSID is of unknown encoding. +// Returns the SSID from |properties| in UTF-8 encoding. If |verbose_logging| is +// true, detailed DEBUG log events will be added to the device event log. If +// |unknown_encoding| != nullptr, it is set to whether the SSID is of unknown +// encoding. CHROMEOS_EXPORT std::string GetSSIDFromProperties( const base::DictionaryValue& properties, + bool verbose_logging, bool* unknown_encoding); // Returns the GUID (if available), SSID, or Name from |properties|. Only used
diff --git a/chromeos/process_proxy/process_proxy.cc b/chromeos/process_proxy/process_proxy.cc index 8fd976b..8a97acb 100644 --- a/chromeos/process_proxy/process_proxy.cc +++ b/chromeos/process_proxy/process_proxy.cc
@@ -237,7 +237,7 @@ // TODO(rvargas) crbug/417532: This is somewhat wrong but the interface of // Open vends pid_t* so ownership is quite vague anyway, and Process::Close // doesn't do much in POSIX. - *pid = process.pid(); + *pid = process.Pid(); return process.IsValid(); }
diff --git a/chromeos/system/statistics_provider.cc b/chromeos/system/statistics_provider.cc index 8451bdf..bac71736 100644 --- a/chromeos/system/statistics_provider.cc +++ b/chromeos/system/statistics_provider.cc
@@ -70,7 +70,9 @@ // Key values for GetMachineStatistic()/GetMachineFlag() calls. const char kActivateDateKey[] = "ActivateDate"; const char kCustomizationIdKey[] = "customization_id"; -const char kDevSwitchBootMode[] = "devsw_boot"; +const char kDevSwitchBootKey[] = "devsw_boot"; +const char kDevSwitchBootValueDev[] = "1"; +const char kDevSwitchBootValueVerified[] = "0"; const char kFirmwareTypeKey[] = "mainfw_type"; const char kFirmwareTypeValueDeveloper[] = "developer"; const char kFirmwareTypeValueNonchrome[] = "nonchrome"; @@ -79,6 +81,9 @@ const char kOffersCouponCodeKey[] = "ubind_attribute"; const char kOffersGroupCodeKey[] = "gbind_attribute"; const char kRlzBrandCodeKey[] = "rlz_brand_code"; +const char kWriteProtectSwitchBootKey[] = "wpsw_boot"; +const char kWriteProtectSwitchBootValueOff[] = "0"; +const char kWriteProtectSwitchBootValueOn[] = "1"; // OEM specific statistics. Must be prefixed with "oem_". const char kOemCanExitEnterpriseEnrollmentKey[] = "oem_can_exit_enrollment";
diff --git a/chromeos/system/statistics_provider.h b/chromeos/system/statistics_provider.h index 3c79bad..e70455f 100644 --- a/chromeos/system/statistics_provider.h +++ b/chromeos/system/statistics_provider.h
@@ -24,7 +24,9 @@ CHROMEOS_EXPORT extern const char kCustomizationIdKey[]; // Developer switch value. -CHROMEOS_EXPORT extern const char kDevSwitchBootMode[]; +CHROMEOS_EXPORT extern const char kDevSwitchBootKey[]; +CHROMEOS_EXPORT extern const char kDevSwitchBootValueVerified[]; +CHROMEOS_EXPORT extern const char kDevSwitchBootValueDev[]; // Firmware type and associated values. The values are from crossystem output // for the mainfw_type key. Normal and developer correspond to Chrome OS @@ -62,6 +64,11 @@ // Release Brand Code key. CHROMEOS_EXPORT extern const char kRlzBrandCodeKey[]; +// Write protect switch value. +CHROMEOS_EXPORT extern const char kWriteProtectSwitchBootKey[]; +CHROMEOS_EXPORT extern const char kWriteProtectSwitchBootValueOff[]; +CHROMEOS_EXPORT extern const char kWriteProtectSwitchBootValueOn[]; + // This interface provides access to Chrome OS statistics. class CHROMEOS_EXPORT StatisticsProvider { public:
diff --git a/components/BUILD.gn b/components/BUILD.gn index 921ac25..4e3d75b8 100644 --- a/components/BUILD.gn +++ b/components/BUILD.gn
@@ -233,7 +233,6 @@ "//components/bookmarks/browser:unit_tests", "//components/captive_portal:unit_tests", "//components/cloud_devices/common:unit_tests", - "//components/component_updater:unit_tests", "//components/content_settings/core/browser:unit_tests", "//components/content_settings/core/common:unit_tests", "//components/crx_file:unit_tests", @@ -250,6 +249,7 @@ "//components/ownership:unit_tests", "//components/packed_ct_ev_whitelist:unit_tests", "//components/proximity_auth:unit_tests", + "//components/update_client:unit_tests", "//components/variations:unit_tests", "//components/web_resource:unit_tests", "//components/webdata/common:unit_tests",
diff --git a/components/app_modal/app_modal_dialog.cc b/components/app_modal/app_modal_dialog.cc index c50a604..8689b7f 100644 --- a/components/app_modal/app_modal_dialog.cc +++ b/components/app_modal/app_modal_dialog.cc
@@ -8,8 +8,6 @@ #include "base/run_loop.h" #include "components/app_modal/app_modal_dialog_queue.h" #include "components/app_modal/native_app_modal_dialog.h" -#include "content/public/browser/web_contents.h" -#include "content/public/browser/web_contents_delegate.h" using content::WebContents; @@ -45,7 +43,6 @@ void AppModalDialog::ShowModalDialog() { native_dialog_ = CreateNativeDialog(); - web_contents_->GetDelegate()->ActivateContents(web_contents_); native_dialog_->ShowAppModalDialog(); if (app_modal_dialog_observer) app_modal_dialog_observer->Notify(this);
diff --git a/components/app_modal/javascript_app_modal_dialog.cc b/components/app_modal/javascript_app_modal_dialog.cc index 27ccd3d3..083f17b 100644 --- a/components/app_modal/javascript_app_modal_dialog.cc +++ b/components/app_modal/javascript_app_modal_dialog.cc
@@ -6,15 +6,8 @@ #include "components/app_modal/javascript_dialog_manager.h" #include "components/app_modal/javascript_native_dialog_factory.h" -#include "content/public/browser/web_contents.h" #include "ui/gfx/text_elider.h" -#if defined(USE_AURA) -#include "ui/aura/window.h" -#include "ui/aura/window_event_dispatcher.h" -#endif - -using content::WebContents; namespace app_modal { namespace { @@ -60,7 +53,7 @@ } JavaScriptAppModalDialog::JavaScriptAppModalDialog( - WebContents* web_contents, + content::WebContents* web_contents, ExtraDataMap* extra_data_map, const base::string16& title, content::JavaScriptMessageType javascript_message_type, @@ -86,17 +79,9 @@ } NativeAppModalDialog* JavaScriptAppModalDialog::CreateNativeDialog() { - gfx::NativeWindow parent_window = web_contents()->GetTopLevelNativeWindow(); - -#if defined(USE_AURA) - if (!parent_window->GetRootWindow()) { - // When we are part of a WebContents that isn't actually being displayed on - // the screen, we can't actually attach to it. - parent_window = NULL; - } -#endif // defined(USE_AURA) - return JavaScriptDialogManager::GetInstance()->native_dialog_factory()-> - CreateNativeJavaScriptDialog(this, parent_window); + return JavaScriptDialogManager::GetInstance() + ->native_dialog_factory() + ->CreateNativeJavaScriptDialog(this); } bool JavaScriptAppModalDialog::IsJavaScriptModalDialog() {
diff --git a/components/app_modal/javascript_native_dialog_factory.h b/components/app_modal/javascript_native_dialog_factory.h index d8f901c..9a88227 100644 --- a/components/app_modal/javascript_native_dialog_factory.h +++ b/components/app_modal/javascript_native_dialog_factory.h
@@ -18,8 +18,7 @@ // Creates an native modal dialog for a JavaScript dialog; virtual NativeAppModalDialog* CreateNativeJavaScriptDialog( - JavaScriptAppModalDialog* dialog, - gfx::NativeWindow parent_window) = 0; + JavaScriptAppModalDialog* dialog) = 0; }; } // namespace app_modal
diff --git a/components/autofill.gypi b/components/autofill.gypi index 682ddfe..4b8ae6f9 100644 --- a/components/autofill.gypi +++ b/components/autofill.gypi
@@ -187,6 +187,8 @@ 'autofill/core/browser/suggestion.h', 'autofill/core/browser/validation.cc', 'autofill/core/browser/validation.h', + 'autofill/core/browser/wallet/real_pan_wallet_client.cc', + 'autofill/core/browser/wallet/real_pan_wallet_client.h', 'autofill/core/browser/webdata/autocomplete_syncable_service.cc', 'autofill/core/browser/webdata/autocomplete_syncable_service.h', 'autofill/core/browser/webdata/autofill_change.cc',
diff --git a/components/autofill/content/renderer/autofill_agent.cc b/components/autofill/content/renderer/autofill_agent.cc index 834c6e8..b0ff55a9 100644 --- a/components/autofill/content/renderer/autofill_agent.cc +++ b/components/autofill/content/renderer/autofill_agent.cc
@@ -213,14 +213,7 @@ if (node.isNull() || !node.isElementNode()) return; - if (node.document().frame() != render_frame()->GetWebFrame()) - return; - WebElement web_element = node.toConst<WebElement>(); - - if (!web_element.document().frame()) - return; - const WebInputElement* element = toWebInputElement(&web_element); if (!element || !element->isEnabled() || element->isReadOnly() || @@ -316,6 +309,9 @@ options.display_warning_if_disabled = true; options.show_full_suggestion_list = element.isAutofilled(); + // On Android, default to showing the dropdown on field focus. + // On desktop, require an extra click after field focus. + // See http://crbug.com/427660 #if defined(OS_ANDROID) bool single_click_autofill = !base::CommandLine::ForCurrentProcess()->HasSwitch( @@ -794,11 +790,6 @@ // No-op. Don't delete |this|. } -void AutofillAgent::LegacyAutofillAgent::FocusedNodeChanged( - const WebNode& node) { - agent_->FocusedNodeChanged(node); -} - void AutofillAgent::LegacyAutofillAgent::FocusChangeComplete() { agent_->FocusChangeComplete(); }
diff --git a/components/autofill/content/renderer/autofill_agent.h b/components/autofill/content/renderer/autofill_agent.h index c03ce87..585c0fe 100644 --- a/components/autofill/content/renderer/autofill_agent.h +++ b/components/autofill/content/renderer/autofill_agent.h
@@ -66,7 +66,6 @@ private: // content::RenderViewObserver: void OnDestruct() override; - void FocusedNodeChanged(const blink::WebNode& node) override; void FocusChangeComplete() override; AutofillAgent* agent_; @@ -114,10 +113,10 @@ void DidFinishDocumentLoad() override; void WillSubmitForm(const blink::WebFormElement& form) override; void DidChangeScrollOffset() override; + void FocusedNodeChanged(const blink::WebNode& node) override; // Pass-through from LegacyAutofillAgent. This correlates with the // RenderViewObserver method. - void FocusedNodeChanged(const blink::WebNode& node); void FocusChangeComplete(); // PageClickListener:
diff --git a/components/autofill/core/browser/BUILD.gn b/components/autofill/core/browser/BUILD.gn index 3a82eaf..92cdc73 100644 --- a/components/autofill/core/browser/BUILD.gn +++ b/components/autofill/core/browser/BUILD.gn
@@ -119,6 +119,8 @@ "suggestion.h", "validation.cc", "validation.h", + "wallet/real_pan_wallet_client.cc", + "wallet/real_pan_wallet_client.h", "webdata/autocomplete_syncable_service.cc", "webdata/autocomplete_syncable_service.h", "webdata/autofill_change.cc",
diff --git a/components/autofill/core/browser/autofill_client.h b/components/autofill/core/browser/autofill_client.h index 6096d013..534aa68 100644 --- a/components/autofill/core/browser/autofill_client.h +++ b/components/autofill/core/browser/autofill_client.h
@@ -13,6 +13,8 @@ #include "base/strings/string16.h" #include "ui/base/window_open_disposition.h" +class IdentityProvider; + namespace content { class RenderFrameHost; } @@ -72,6 +74,9 @@ // Gets the preferences associated with the client. virtual PrefService* GetPrefs() = 0; + // Gets the IdentityProvider associated with the client (for OAuth2). + virtual IdentityProvider* GetIdentityProvider() = 0; + // Hides the associated request autocomplete dialog (if it exists). virtual void HideRequestAutocompleteDialog() = 0;
diff --git a/components/autofill/core/browser/autofill_manager.cc b/components/autofill/core/browser/autofill_manager.cc index b9123d0..b04ff56 100644 --- a/components/autofill/core/browser/autofill_manager.cc +++ b/components/autofill/core/browser/autofill_manager.cc
@@ -145,6 +145,7 @@ AutofillDownloadManagerState enable_download_manager) : driver_(driver), client_(client), + real_pan_client_(driver->GetURLRequestContext(), this), app_locale_(app_locale), personal_data_(client->GetPersonalDataManager()), autocomplete_history_manager_( @@ -560,6 +561,8 @@ unmasking_query_id_ = query_id; unmasking_form_ = form; unmasking_field_ = field; + // TODO(estade): uncomment this after the demo. + // real_pan_client_.Prepare(); client()->ShowUnmaskPrompt(unmasking_card_, weak_ptr_factory_.GetWeakPtr()); return; @@ -680,7 +683,13 @@ driver_->SendAutofillTypePredictionsToRenderer(form_structures_.get()); } -void AutofillManager::OnUnmaskResponse(const base::string16& cvc) { +void AutofillManager::OnUnmaskResponse(const base::string16& cvc, + const base::string16& exp_month, + const base::string16& exp_year) { + // Most of this function is demo code. The real code should look something + // like: + // real_pan_client_.UnmaskCard(unmasking_card_, cvc, exp_month, exp_year); + unmasking_cvc_ = cvc; // TODO(estade): fake verification: assume 123/1234 is the correct cvc. if (StartsWithASCII(base::UTF16ToASCII(cvc), "123", true)) { @@ -697,16 +706,27 @@ } void AutofillManager::OnUnmaskPromptClosed() { + real_pan_client_.CancelRequest(); driver_->RendererShouldClearPreviewedForm(); unmasking_card_ = CreditCard(); unmasking_cvc_.clear(); } +IdentityProvider* AutofillManager::GetIdentityProvider() { + return client()->GetIdentityProvider(); +} + +void AutofillManager::OnDidGetRealPan(const std::string& real_pan) { + NOTIMPLEMENTED(); +} + void AutofillManager::OnUnmaskVerificationResult(bool success) { if (success) { unmasking_card_.set_record_type(CreditCard::FULL_SERVER_CARD); if (unmasking_card_.type() == kAmericanExpressCard) { unmasking_card_.SetNumber(base::ASCIIToUTF16("371449635398431")); + } else if (unmasking_card_.type() == kVisaCard) { + unmasking_card_.SetNumber(base::ASCIIToUTF16("4012888888881881")); } else { DCHECK_EQ(kDiscoverCard, unmasking_card_.type()); unmasking_card_.SetNumber(base::ASCIIToUTF16("6011000990139424")); @@ -847,6 +867,7 @@ PersonalDataManager* personal_data) : driver_(driver), client_(client), + real_pan_client_(driver->GetURLRequestContext(), this), app_locale_("en-US"), personal_data_(personal_data), autocomplete_history_manager_(
diff --git a/components/autofill/core/browser/autofill_manager.h b/components/autofill/core/browser/autofill_manager.h index ec9286c..4b0ce90 100644 --- a/components/autofill/core/browser/autofill_manager.h +++ b/components/autofill/core/browser/autofill_manager.h
@@ -26,6 +26,7 @@ #include "components/autofill/core/browser/card_unmask_delegate.h" #include "components/autofill/core/browser/form_structure.h" #include "components/autofill/core/browser/personal_data_manager.h" +#include "components/autofill/core/browser/wallet/real_pan_wallet_client.h" #include "components/autofill/core/common/form_data.h" namespace gfx { @@ -56,7 +57,8 @@ // Manages saving and restoring the user's personal information entered into web // forms. One per frame; owned by the AutofillDriver. class AutofillManager : public AutofillDownloadManager::Observer, - public CardUnmaskDelegate { + public CardUnmaskDelegate, + public wallet::RealPanWalletClient::Delegate { public: enum AutofillDownloadManagerState { ENABLE_AUTOFILL_DOWNLOAD_MANAGER, @@ -224,9 +226,15 @@ void OnLoadedServerPredictions(const std::string& response_xml) override; // CardUnmaskDelegate: - void OnUnmaskResponse(const base::string16& cvc) override; + void OnUnmaskResponse(const base::string16& cvc, + const base::string16& exp_month, + const base::string16& exp_year) override; void OnUnmaskPromptClosed() override; + // wallet::RealPanWalletClient::Delegate: + IdentityProvider* GetIdentityProvider() override; + void OnDidGetRealPan(const std::string& real_pan) override; + // A toy method called when the (fake) unmasking process has finished. void OnUnmaskVerificationResult(bool success); @@ -315,6 +323,9 @@ AutofillClient* const client_; + // Handles real PAN requests. + wallet::RealPanWalletClient real_pan_client_; + std::string app_locale_; // The personal data manager, used to save and load personal data to/from the
diff --git a/components/autofill/core/browser/card_unmask_delegate.h b/components/autofill/core/browser/card_unmask_delegate.h index 4ace1ec..0ce1a875 100644 --- a/components/autofill/core/browser/card_unmask_delegate.h +++ b/components/autofill/core/browser/card_unmask_delegate.h
@@ -13,7 +13,9 @@ public: // Called when the user has attempted a verification. Prompt is still // open at this point. - virtual void OnUnmaskResponse(const base::string16& cvc) = 0; + virtual void OnUnmaskResponse(const base::string16& cvc, + const base::string16& exp_month, + const base::string16& exp_year) = 0; // Called when the unmask prompt is closed (e.g., cancelled). virtual void OnUnmaskPromptClosed() = 0;
diff --git a/components/autofill/core/browser/credit_card.cc b/components/autofill/core/browser/credit_card.cc index 448feb9..cfae31bb 100644 --- a/components/autofill/core/browser/credit_card.cc +++ b/components/autofill/core/browser/credit_card.cc
@@ -132,14 +132,16 @@ record_type_(LOCAL_CARD), type_(kGenericCard), expiration_month_(0), - expiration_year_(0) { + expiration_year_(0), + server_status_(OK) { } CreditCard::CreditCard(const base::string16& card_number, int expiration_month, int expiration_year) : AutofillDataModel(std::string(), std::string()), - record_type_(LOCAL_CARD) { + record_type_(LOCAL_CARD), + server_status_(OK) { SetNumber(card_number); SetExpirationMonth(expiration_month); SetExpirationYear(expiration_year); @@ -151,7 +153,8 @@ type_(kGenericCard), expiration_month_(0), expiration_year_(0), - server_id_(server_id) { + server_id_(server_id), + server_status_(OK) { DCHECK(type == MASKED_SERVER_CARD || type == FULL_SERVER_CARD); } @@ -160,7 +163,8 @@ record_type_(LOCAL_CARD), type_(kGenericCard), expiration_month_(0), - expiration_year_(0) { + expiration_year_(0), + server_status_(OK) { } CreditCard::CreditCard(const CreditCard& credit_card) @@ -307,6 +311,16 @@ type_ = type; } +void CreditCard::SetServerStatus(ServerStatus status) { + DCHECK_NE(LOCAL_CARD, record_type()); + server_status_ = status; +} + +CreditCard::ServerStatus CreditCard::GetServerStatus() const { + DCHECK_NE(LOCAL_CARD, record_type()); + return server_status_; +} + base::string16 CreditCard::GetRawInfo(ServerFieldType type) const { DCHECK_EQ(CREDIT_CARD, AutofillType(type).group()); switch (type) { @@ -525,6 +539,7 @@ expiration_month_ = credit_card.expiration_month_; expiration_year_ = credit_card.expiration_year_; server_id_ = credit_card.server_id_; + server_status_ = credit_card.server_status_; set_guid(credit_card.guid()); set_origin(credit_card.origin()); @@ -579,6 +594,12 @@ if (comparison != 0) return comparison; + if (static_cast<int>(server_status_) < + static_cast<int>(credit_card.server_status_)) + return -1; + if (static_cast<int>(server_status_) > + static_cast<int>(credit_card.server_status_)) + return 1; if (static_cast<int>(record_type_) < static_cast<int>(credit_card.record_type_)) return -1;
diff --git a/components/autofill/core/browser/credit_card.h b/components/autofill/core/browser/credit_card.h index 181001c..d8eda0a9 100644 --- a/components/autofill/core/browser/credit_card.h +++ b/components/autofill/core/browser/credit_card.h
@@ -33,6 +33,12 @@ FULL_SERVER_CARD, }; + // The status of this credit card. Only used for server cards. + enum ServerStatus { + EXPIRED, + OK, + }; + CreditCard(const std::string& guid, const std::string& origin); CreditCard(const base::string16& card_number, int expiration_month, @@ -72,6 +78,10 @@ // Type strings are defined at the bottom of this file, e.g. kVisaCard. void SetTypeForMaskedCard(const char* type); + // Sets/gets the status of a server card. + void SetServerStatus(ServerStatus status); + ServerStatus GetServerStatus() const; + // FormGroup: void GetMatchingTypes(const base::string16& text, const std::string& app_locale, @@ -199,6 +209,10 @@ // For server cards (both MASKED and UNMASKED) this is the ID assigned by the // server to uniquely identify this card. std::string server_id_; + + // The status of the card, as reported by the server. Not valid for local + // cards. + ServerStatus server_status_; }; // So we can compare CreditCards with EXPECT_EQ().
diff --git a/components/autofill/core/browser/credit_card_unittest.cc b/components/autofill/core/browser/credit_card_unittest.cc index 5d399be1..bb74d40 100644 --- a/components/autofill/core/browser/credit_card_unittest.cc +++ b/components/autofill/core/browser/credit_card_unittest.cc
@@ -145,7 +145,7 @@ EXPECT_TRUE(a == b); } -TEST(CreditCardTest, Compare) { +TEST(CreditCardTest, IsLocalDuplicateOfServerCard) { struct { CreditCard::RecordType first_card_record_type; const char* first_card_name; @@ -217,7 +217,7 @@ } } -TEST(CreditCardTest, IsLocalDuplicateOfServerCard) { +TEST(CreditCardTest, Compare) { CreditCard a(base::GenerateGUID(), std::string()); CreditCard b(base::GenerateGUID(), std::string());
diff --git a/components/autofill/core/browser/test_autofill_client.cc b/components/autofill/core/browser/test_autofill_client.cc index 34523dd..e193a3a 100644 --- a/components/autofill/core/browser/test_autofill_client.cc +++ b/components/autofill/core/browser/test_autofill_client.cc
@@ -14,17 +14,21 @@ } PersonalDataManager* TestAutofillClient::GetPersonalDataManager() { - return NULL; + return nullptr; } scoped_refptr<AutofillWebDataService> TestAutofillClient::GetDatabase() { - return scoped_refptr<AutofillWebDataService>(NULL); + return scoped_refptr<AutofillWebDataService>(nullptr); } PrefService* TestAutofillClient::GetPrefs() { return prefs_.get(); } +IdentityProvider* TestAutofillClient::GetIdentityProvider() { + return nullptr; +} + void TestAutofillClient::HideRequestAutocompleteDialog() { }
diff --git a/components/autofill/core/browser/test_autofill_client.h b/components/autofill/core/browser/test_autofill_client.h index 25c5308..571d04e 100644 --- a/components/autofill/core/browser/test_autofill_client.h +++ b/components/autofill/core/browser/test_autofill_client.h
@@ -23,6 +23,7 @@ PersonalDataManager* GetPersonalDataManager() override; scoped_refptr<AutofillWebDataService> GetDatabase() override; PrefService* GetPrefs() override; + IdentityProvider* GetIdentityProvider() override; void HideRequestAutocompleteDialog() override; void ShowAutofillSettings() override; void ShowUnmaskPrompt(const CreditCard& card,
diff --git a/components/autofill/core/browser/wallet/real_pan_wallet_client.cc b/components/autofill/core/browser/wallet/real_pan_wallet_client.cc new file mode 100644 index 0000000..35c6cbd --- /dev/null +++ b/components/autofill/core/browser/wallet/real_pan_wallet_client.cc
@@ -0,0 +1,186 @@ +// Copyright 2015 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/autofill/core/browser/wallet/real_pan_wallet_client.h" + +#include "base/bind.h" +#include "base/json/json_reader.h" +#include "base/json/json_writer.h" +#include "base/memory/scoped_ptr.h" +#include "base/strings/stringprintf.h" +#include "base/values.h" +#include "components/autofill/core/browser/credit_card.h" +#include "google_apis/gaia/identity_provider.h" +#include "net/base/escape.h" +#include "net/http/http_status_code.h" +#include "net/url_request/url_fetcher.h" +#include "net/url_request/url_request_context_getter.h" + +namespace autofill { +namespace wallet { + +namespace { + +const char kUnmaskCardRequestFormat[] = + "request_content_type=application/json&request=%s&cvc=%s"; + +// TODO(estade): use a sandbox server on dev builds? +const char kUnmaskCardRequestUrl[] = + "https://wallet.google.com/payments/apis-secure/creditcardservice" + "/GetRealPan?s7e=cvc"; + +const char kTokenServiceConsumerId[] = "real_pan_wallet_client"; +const char kWalletOAuth2Scope[] = + "https://www.googleapis.com/auth/wallet.chrome"; + +} // namespace + +RealPanWalletClient::RealPanWalletClient( + net::URLRequestContextGetter* context_getter, + Delegate* delegate) + : OAuth2TokenService::Consumer(kTokenServiceConsumerId), + context_getter_(context_getter), + delegate_(delegate), + weak_ptr_factory_(this) { + DCHECK(delegate); +} + +RealPanWalletClient::~RealPanWalletClient() { +} + +void RealPanWalletClient::Prepare() { + if (access_token_.empty()) + StartTokenFetch(); +} + +void RealPanWalletClient::UnmaskCard(const CreditCard& card, + const std::string& cvc) { + DCHECK_EQ(CreditCard::MASKED_SERVER_CARD, card.record_type()); + + request_.reset(net::URLFetcher::Create( + 0, GURL(kUnmaskCardRequestUrl), net::URLFetcher::POST, this)); + request_->SetRequestContext(context_getter_.get()); + + base::DictionaryValue request_dict; + request_dict.SetString("encrypted_cvc", "__param:cvc"); + // TODO(estade): is this the correct "token"? + request_dict.SetString("credit_card_token", card.server_id()); + std::string json_request; + base::JSONWriter::Write(&request_dict, &json_request); + std::string post_body = base::StringPrintf(kUnmaskCardRequestFormat, + net::EscapeUrlEncodedData(json_request, true).c_str(), + net::EscapeUrlEncodedData(cvc, true).c_str()); + request_->SetUploadData("application/x-www-form-urlencoded", post_body); + + if (access_token_.empty()) + StartTokenFetch(); + else + SetOAuth2TokenAndStartRequest(); +} + +void RealPanWalletClient::CancelRequest() { + request_.reset(); +} + +void RealPanWalletClient::OnURLFetchComplete(const net::URLFetcher* source) { + DCHECK_EQ(source, request_.get()); + + // |request_|, which is aliased to |source|, might continue to be used in this + // |method, but should be freed once control leaves the method. + scoped_ptr<net::URLFetcher> scoped_request(request_.Pass()); + scoped_ptr<base::DictionaryValue> response_dict; + int response_code = source->GetResponseCode(); + + // TODO(estade): OAuth2 may fail due to an expired access token, in which case + // we should invalidate the token and try again. How is that failure reported? + + switch (response_code) { + // Valid response. + case net::HTTP_OK: { + std::string data; + source->GetResponseAsString(&data); + scoped_ptr<base::Value> message_value(base::JSONReader::Read(data)); + if (message_value.get() && + message_value->IsType(base::Value::TYPE_DICTIONARY)) { + response_dict.reset( + static_cast<base::DictionaryValue*>(message_value.release())); + } else { + NOTIMPLEMENTED(); + } + break; + } + + // HTTP_BAD_REQUEST means the arguments are invalid. No point retrying. + case net::HTTP_BAD_REQUEST: { + NOTIMPLEMENTED(); + break; + } + + // Response contains an error to show the user. + case net::HTTP_FORBIDDEN: + case net::HTTP_INTERNAL_SERVER_ERROR: { + NOTIMPLEMENTED(); + break; + } + + // Handle anything else as a generic error. + default: + NOTIMPLEMENTED(); + break; + } + + std::string real_pan; + if (response_dict) + response_dict->GetString("pan", &real_pan); + delegate_->OnDidGetRealPan(real_pan); +} + +void RealPanWalletClient::OnGetTokenSuccess( + const OAuth2TokenService::Request* request, + const std::string& access_token, + const base::Time& expiration_time) { + DCHECK_EQ(request, access_token_request_.get()); + access_token_ = access_token; + if (request_) + SetOAuth2TokenAndStartRequest(); + + access_token_request_.reset(); +} + +void RealPanWalletClient::OnGetTokenFailure( + const OAuth2TokenService::Request* request, + const GoogleServiceAuthError& error) { + DCHECK_EQ(request, access_token_request_.get()); + if (request_) { + request_.reset(); + delegate_->OnDidGetRealPan(std::string()); + } + // TODO(estade): what do we do in the failure case? + NOTIMPLEMENTED(); + + access_token_request_.reset(); +} + +void RealPanWalletClient::StartTokenFetch() { + // Don't cancel outstanding requests. + if (access_token_request_) + return; + + // However, do clear old tokens. + access_token_.clear(); + + OAuth2TokenService::ScopeSet wallet_scopes; + wallet_scopes.insert(kWalletOAuth2Scope); + IdentityProvider* identity = delegate_->GetIdentityProvider(); + access_token_request_ = identity->GetTokenService()->StartRequest( + identity->GetActiveAccountId(), wallet_scopes, this); +} + +void RealPanWalletClient::SetOAuth2TokenAndStartRequest() { + request_->AddExtraRequestHeader("Authorization: " + access_token_); + request_->Start(); +} + +} // namespace wallet +} // namespace autofill
diff --git a/components/autofill/core/browser/wallet/real_pan_wallet_client.h b/components/autofill/core/browser/wallet/real_pan_wallet_client.h new file mode 100644 index 0000000..3323f91 --- /dev/null +++ b/components/autofill/core/browser/wallet/real_pan_wallet_client.h
@@ -0,0 +1,102 @@ +// Copyright 2015 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_AUTOFILL_CORE_BROWSER_WALLET_REAL_PAN_WALLET_CLIENT_H_ +#define COMPONENTS_AUTOFILL_CORE_BROWSER_WALLET_REAL_PAN_WALLET_CLIENT_H_ + +#include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" +#include "google_apis/gaia/oauth2_token_service.h" +#include "net/url_request/url_fetcher_delegate.h" + +class IdentityProvider; + +namespace net { +class URLFetcher; +class URLRequestContextGetter; +} + +namespace autofill { + +class CreditCard; + +namespace wallet { + +// RealPanWalletClient is modelled on WalletClient. Whereas the latter is used +// for requestAutocomplete-related requests, RealPanWalletClient is used to +// import user data from Wallet for normal web Autofill. +class RealPanWalletClient : public net::URLFetcherDelegate, + public OAuth2TokenService::Consumer { + public: + class Delegate { + public: + // The identity provider used to get OAuth2 tokens. + virtual IdentityProvider* GetIdentityProvider() = 0; + + // Returns the real PAN retrieved from Wallet. |real_pan| will be empty + // on failure. + virtual void OnDidGetRealPan(const std::string& real_pan) = 0; + }; + + // |context_getter| is reference counted so it has no lifetime or ownership + // requirements. |delegate| must outlive |this|. |source_url| is the url + // of the merchant page. + RealPanWalletClient(net::URLRequestContextGetter* context_getter, + Delegate* delegate); + + ~RealPanWalletClient() override; + + // Starts fetching the OAuth2 token in anticipation of future wallet requests. + // Called as an optimization, but not strictly necessary. + void Prepare(); + + // The user has attempted to unmask a card with the given cvc. + void UnmaskCard(const CreditCard& card, const std::string& cvc); + + // Cancels and clears the current |request_|. + void CancelRequest(); + + private: + // net::URLFetcherDelegate: + void OnURLFetchComplete(const net::URLFetcher* source) override; + + // OAuth2TokenService::Consumer implementation. + void OnGetTokenSuccess(const OAuth2TokenService::Request* request, + const std::string& access_token, + const base::Time& expiration_time) override; + void OnGetTokenFailure(const OAuth2TokenService::Request* request, + const GoogleServiceAuthError& error) override; + + // Initiates a new OAuth2 token request. + void StartTokenFetch(); + + // Adds the token to |request_| and starts the request. + void SetOAuth2TokenAndStartRequest(); + + // The context for the request. Ensures the gdToken cookie is set as a header + // in the requests to Online Wallet if it is present. + scoped_refptr<net::URLRequestContextGetter> context_getter_; + + // Observer class that has its various On* methods called based on the results + // of a request to Online Wallet. + Delegate* const delegate_; // must outlive |this|. + + // The current Wallet request object. + scoped_ptr<net::URLFetcher> request_; + + // The current OAuth2 token request object; + scoped_ptr<OAuth2TokenService::Request> access_token_request_; + + // The OAuth2 token, or empty if not fetched. + std::string access_token_; + + base::WeakPtrFactory<RealPanWalletClient> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(RealPanWalletClient); +}; + +} // namespace wallet +} // namespace autofill + +#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_WALLET_REAL_PAN_WALLET_CLIENT_H_
diff --git a/components/autofill/core/browser/webdata/autofill_table.cc b/components/autofill/core/browser/webdata/autofill_table.cc index 197d800..4f4c8157 100644 --- a/components/autofill/core/browser/webdata/autofill_table.cc +++ b/components/autofill/core/browser/webdata/autofill_table.cc
@@ -445,6 +445,27 @@ return end.ToTimeT(); } +std::string ServerStatusEnumToString(CreditCard::ServerStatus status) { + switch (status) { + case CreditCard::EXPIRED: + return "EXPIRED"; + + case CreditCard::OK: + return "OK"; + } + + NOTREACHED(); + return "OK"; +} + +CreditCard::ServerStatus ServerStatusStringToEnum(const std::string& status) { + if (status == "EXPIRED") + return CreditCard::EXPIRED; + + DCHECK_EQ("OK", status); + return CreditCard::OK; +} + } // namespace // The maximum length allowed for form data. @@ -1229,7 +1250,7 @@ DCHECK_EQ(CreditCard::GetCreditCardType(full_card_number), card_type); } - index++; // TODO(brettw) hook up status. For now, skip over it. + card->SetServerStatus(ServerStatusStringToEnum(s.ColumnString(index++))); card->SetRawInfo(CREDIT_CARD_NAME, s.ColumnString16(index++)); card->SetRawInfo(CREDIT_CARD_EXP_MONTH, s.ColumnString16(index++)); card->SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, s.ColumnString16(index++)); @@ -1267,6 +1288,19 @@ ASCIIToUTF16("9424")); fake_masked_cards.back().SetTypeForMaskedCard(kDiscoverCard); + fake_masked_cards.push_back( + CreditCard(CreditCard::MASKED_SERVER_CARD, "c789")); + fake_masked_cards.back().SetRawInfo(CREDIT_CARD_NAME, + ASCIIToUTF16("Efren Salazar, Sr")); + fake_masked_cards.back().SetRawInfo(CREDIT_CARD_EXP_MONTH, + ASCIIToUTF16("12")); + fake_masked_cards.back().SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, + ASCIIToUTF16("2014")); + fake_masked_cards.back().SetRawInfo(CREDIT_CARD_NUMBER, + ASCIIToUTF16("1881")); + fake_masked_cards.back().SetTypeForMaskedCard(kVisaCard); + fake_masked_cards.back().SetServerStatus(CreditCard::EXPIRED); + SetServerCreditCards(fake_masked_cards); return GetServerCreditCards(credit_cards); } @@ -1326,7 +1360,8 @@ masked_insert.BindString(0, card.server_id()); masked_insert.BindString(1, card.type()); - masked_insert.BindNull(2); // Skip status which doesn't have storage yet. + masked_insert.BindString(2, + ServerStatusEnumToString(card.GetServerStatus())); masked_insert.BindString16(3, card.GetRawInfo(CREDIT_CARD_NAME)); masked_insert.BindString16(4, card.LastFourDigits()); masked_insert.BindString16(5, card.GetRawInfo(CREDIT_CARD_EXP_MONTH));
diff --git a/components/autofill/core/browser/webdata/autofill_table_unittest.cc b/components/autofill/core/browser/webdata/autofill_table_unittest.cc index dceac51..75eec07 100644 --- a/components/autofill/core/browser/webdata/autofill_table_unittest.cc +++ b/components/autofill/core/browser/webdata/autofill_table_unittest.cc
@@ -1621,6 +1621,7 @@ inputs[1].SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, ASCIIToUTF16("1997")); inputs[1].SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("1111")); inputs[1].SetTypeForMaskedCard(kVisaCard); + inputs[1].SetServerStatus(CreditCard::EXPIRED); table_->SetServerCreditCards(inputs); @@ -1643,6 +1644,9 @@ EXPECT_EQ(inputs[0], *outputs[0]); EXPECT_EQ(inputs[1], *outputs[1]); + EXPECT_EQ(CreditCard::OK, outputs[0]->GetServerStatus()); + EXPECT_EQ(CreditCard::EXPIRED, outputs[1]->GetServerStatus()); + STLDeleteContainerPointers(outputs.begin(), outputs.end()); }
diff --git a/components/autofill/core/common/password_form.h b/components/autofill/core/common/password_form.h index 039e644..be85cd3e 100644 --- a/components/autofill/core/common/password_form.h +++ b/components/autofill/core/common/password_form.h
@@ -189,7 +189,7 @@ TYPE_LAST = TYPE_GENERATED }; - // The form type. Not used yet. Please see http://crbug.com/152422 + // The form type. Type type; // The number of times that this username/password has been used to
diff --git a/components/browser_watcher/exit_code_watcher_win.cc b/components/browser_watcher/exit_code_watcher_win.cc index 218978c..0e231847 100644 --- a/components/browser_watcher/exit_code_watcher_win.cc +++ b/components/browser_watcher/exit_code_watcher_win.cc
@@ -30,7 +30,12 @@ } bool ExitCodeWatcher::Initialize(base::Process process) { - DWORD process_pid = process.pid(); + if (!process.IsValid()) { + LOG(ERROR) << "Invalid parent handle, can't get parent process ID."; + return false; + } + + DWORD process_pid = process.Pid(); if (process_pid == 0) { LOG(ERROR) << "Invalid parent handle, can't get parent process ID."; return false; @@ -44,7 +49,7 @@ return false; } - // Success, take ownership of the process handle. + // Success, take ownership of the process. process_ = process.Pass(); process_creation_time_ = base::Time::FromFileTime(creation_time); @@ -68,7 +73,7 @@ registry_path_.c_str(), KEY_WRITE); base::string16 value_name( - GetValueName(process_creation_time_, process_.pid())); + GetValueName(process_creation_time_, process_.Pid())); ULONG result = key.WriteValue(value_name.c_str(), exit_code); if (result != ERROR_SUCCESS) {
diff --git a/components/browser_watcher/exit_code_watcher_win_unittest.cc b/components/browser_watcher/exit_code_watcher_win_unittest.cc index a6da2a50..a5ba3337 100644 --- a/components/browser_watcher/exit_code_watcher_win_unittest.cc +++ b/components/browser_watcher/exit_code_watcher_win_unittest.cc
@@ -98,10 +98,7 @@ } base::Process OpenSelfWithAccess(uint32 access) { - HANDLE self = nullptr; - EXPECT_TRUE(base::OpenProcessHandleWithAccess(base::GetCurrentProcId(), - access, &self)); - return base::Process(self); + return base::Process::OpenWithAccess(base::GetCurrentProcId(), access); } void VerifyWroteExitCode(base::ProcessId proc_id, int exit_code) { @@ -172,7 +169,7 @@ EXPECT_TRUE(watcher.Initialize(sleeper.process().Duplicate())); // Verify that the watcher wrote a sentinel for the process. - VerifyWroteExitCode(sleeper.process().pid(), STILL_ACTIVE); + VerifyWroteExitCode(sleeper.process().Pid(), STILL_ACTIVE); // Kill the sleeper, and make sure it's exited before we continue. ASSERT_NO_FATAL_FAILURE(sleeper.Kill(kExitCode, true)); @@ -180,7 +177,7 @@ watcher.WaitForExit(); EXPECT_EQ(kExitCode, watcher.exit_code()); - VerifyWroteExitCode(sleeper.process().pid(), kExitCode); + VerifyWroteExitCode(sleeper.process().Pid(), kExitCode); } } // namespace browser_watcher
diff --git a/components/browser_watcher/watcher_metrics_provider_win.cc b/components/browser_watcher/watcher_metrics_provider_win.cc index 0f94738..0848046 100644 --- a/components/browser_watcher/watcher_metrics_provider_win.cc +++ b/components/browser_watcher/watcher_metrics_provider_win.cc
@@ -145,10 +145,13 @@ events_out->swap(events); } -void RecordSingleExitFunnel(base::win::RegKey* parent_key, - const base::char16* name) { +void MaybeRecordSingleExitFunnel(base::win::RegKey* parent_key, + const base::char16* name, + bool report) { std::vector<std::pair<base::string16, int64>> events; ReadSingleExitFunnel(parent_key, name, &events); + if (!report) + return; // Find the earliest event time. int64 min_time = std::numeric_limits<int64>::max(); @@ -173,7 +176,7 @@ } } -void RecordExitFunnels(const base::string16& registry_path) { +void MaybeRecordExitFunnels(const base::string16& registry_path, bool report) { base::win::RegistryKeyIterator it(HKEY_CURRENT_USER, registry_path.c_str()); if (!it.Valid()) return; @@ -196,7 +199,7 @@ for (; it.Valid(); ++it) { // Defer reporting on still-live processes. if (IsDeadProcess(it.Name())) { - RecordSingleExitFunnel(&key, it.Name()); + MaybeRecordSingleExitFunnel(&key, it.Name(), report); to_delete.push_back(it.Name()); } } @@ -216,7 +219,9 @@ "Stability.ExitFunnel."; WatcherMetricsProviderWin::WatcherMetricsProviderWin( - const base::char16* registry_path) : registry_path_(registry_path) { + const base::char16* registry_path, bool report_exit_funnels) : + registry_path_(registry_path), + report_exit_funnels_(report_exit_funnels) { } WatcherMetricsProviderWin::~WatcherMetricsProviderWin() { @@ -231,7 +236,7 @@ // necessary to implement some form of global locking, which is not worth it // here. RecordExitCodes(registry_path_); - RecordExitFunnels(registry_path_); + MaybeRecordExitFunnels(registry_path_, report_exit_funnels_); } } // namespace browser_watcher
diff --git a/components/browser_watcher/watcher_metrics_provider_win.h b/components/browser_watcher/watcher_metrics_provider_win.h index d2a47545..0004be3 100644 --- a/components/browser_watcher/watcher_metrics_provider_win.h +++ b/components/browser_watcher/watcher_metrics_provider_win.h
@@ -27,7 +27,10 @@ static const char kBrowserExitCodeHistogramName[]; static const char kExitFunnelHistogramPrefix[]; - explicit WatcherMetricsProviderWin(const base::char16* registry_path); + // Initializes the reporter. If |report_exit_funnels| is false, the provider + // will clear the registry data, but not report it. + WatcherMetricsProviderWin(const base::char16* registry_path, + bool report_exit_funnels); ~WatcherMetricsProviderWin(); // metrics::MetricsProvider implementation. @@ -36,6 +39,7 @@ private: base::string16 registry_path_; + bool report_exit_funnels_; DISALLOW_COPY_AND_ASSIGN(WatcherMetricsProviderWin); };
diff --git a/components/browser_watcher/watcher_metrics_provider_win_unittest.cc b/components/browser_watcher/watcher_metrics_provider_win_unittest.cc index 838b12d..820ad34 100644 --- a/components/browser_watcher/watcher_metrics_provider_win_unittest.cc +++ b/components/browser_watcher/watcher_metrics_provider_win_unittest.cc
@@ -81,7 +81,7 @@ // Record a single failure. AddProcessExitCode(false, 100); - WatcherMetricsProviderWin provider(kRegistryPath); + WatcherMetricsProviderWin provider(kRegistryPath, true); provider.ProvideStabilityMetrics(NULL); histogram_tester_.ExpectBucketCount( @@ -103,7 +103,7 @@ // Record own process as STILL_ACTIVE. AddProcessExitCode(true, STILL_ACTIVE); - WatcherMetricsProviderWin provider(kRegistryPath); + WatcherMetricsProviderWin provider(kRegistryPath, true); provider.ProvideStabilityMetrics(NULL); histogram_tester_.ExpectUniqueSample( @@ -122,7 +122,7 @@ AddExitFunnelEvent(100, L"Two", 1010 * 1000); AddExitFunnelEvent(100, L"Three", 990 * 1000); - WatcherMetricsProviderWin provider(kRegistryPath); + WatcherMetricsProviderWin provider(kRegistryPath, true); provider.ProvideStabilityMetrics(NULL); histogram_tester_.ExpectUniqueSample("Stability.ExitFunnel.Three", 0, 1); @@ -135,7 +135,7 @@ } TEST_F(WatcherMetricsProviderWinTest, ReadsExitFunnelWrites) { - // Test that the metrics provider picks up the writes from + // Test that the metrics provider picks up the writes from the funnel. ExitFunnel funnel; // Events against our own process should not get reported. @@ -153,7 +153,7 @@ ASSERT_TRUE(funnel.RecordEvent(L"Two")); ASSERT_TRUE(funnel.RecordEvent(L"Three")); - WatcherMetricsProviderWin provider(kRegistryPath); + WatcherMetricsProviderWin provider(kRegistryPath, true); provider.ProvideStabilityMetrics(NULL); histogram_tester_.ExpectTotalCount("Stability.ExitFunnel.One", 1); @@ -165,4 +165,37 @@ ASSERT_EQ(it.SubkeyCount(), 1); } +TEST_F(WatcherMetricsProviderWinTest, ClearsExitFunnelWriteWhenNotReporting) { + // Tests that the metrics provider cleans up, but doesn't report exit funnels + // when funnel reporting is quenched. + ExitFunnel funnel; + + // Events against our own process should not get reported. + ASSERT_TRUE(funnel.Init(kRegistryPath, base::GetCurrentProcessHandle())); + ASSERT_TRUE(funnel.RecordEvent(L"Forgetaboutit")); + + // Reset the funnel to a pseudo process. The PID 4 is the system process, + // which tests can hopefully never open. + ASSERT_TRUE(funnel.InitImpl(kRegistryPath, 4, base::Time::Now())); + + // Each named event can only exist in a single copy. + ASSERT_TRUE(funnel.RecordEvent(L"One")); + ASSERT_TRUE(funnel.RecordEvent(L"One")); + ASSERT_TRUE(funnel.RecordEvent(L"One")); + ASSERT_TRUE(funnel.RecordEvent(L"Two")); + ASSERT_TRUE(funnel.RecordEvent(L"Three")); + + // Turn off exit funnel reporting. + WatcherMetricsProviderWin provider(kRegistryPath, false); + + provider.ProvideStabilityMetrics(NULL); + histogram_tester_.ExpectTotalCount("Stability.ExitFunnel.One", 0); + histogram_tester_.ExpectTotalCount("Stability.ExitFunnel.Two", 0); + histogram_tester_.ExpectTotalCount("Stability.ExitFunnel.Three", 0); + + // Make sure the subkey for the pseudo process has been deleted on reporting. + base::win::RegistryKeyIterator it(HKEY_CURRENT_USER, kRegistryPath); + ASSERT_EQ(it.SubkeyCount(), 1); +} + } // namespace browser_watcher
diff --git a/components/cloud_devices/common/cloud_devices_switches.cc b/components/cloud_devices/common/cloud_devices_switches.cc index a65f910..83667fa 100644 --- a/components/cloud_devices/common/cloud_devices_switches.cc +++ b/components/cloud_devices/common/cloud_devices_switches.cc
@@ -6,9 +6,6 @@ namespace switches { -// Enable Google Cloud Devices code. -const char kEnableCloudDevices[] = "enable-cloud-devices"; - // The URL of the cloud print service to use, overrides any value stored in // preferences, and the default. Only used if the cloud print service has been // enabled. Used for testing.
diff --git a/components/cloud_devices/common/cloud_devices_switches.h b/components/cloud_devices/common/cloud_devices_switches.h index 343cf66..2a57d735 100644 --- a/components/cloud_devices/common/cloud_devices_switches.h +++ b/components/cloud_devices/common/cloud_devices_switches.h
@@ -7,7 +7,6 @@ namespace switches { -extern const char kEnableCloudDevices[]; extern const char kCloudPrintURL[]; extern const char kCloudPrintXmppEndpoint[]; extern const char kCloudDevicesURL[];
diff --git a/components/component_updater.gypi b/components/component_updater.gypi index bdec48ce..baa0801 100644 --- a/components/component_updater.gypi +++ b/components/component_updater.gypi
@@ -10,72 +10,25 @@ 'type': 'static_library', 'dependencies': [ '../base/base.gyp:base', - '../courgette/courgette.gyp:courgette_lib', - '../crypto/crypto.gyp:crypto', - '../third_party/libxml/libxml.gyp:libxml', - '../third_party/zlib/google/zip.gyp:zip', - '../net/net.gyp:net', '../ui/base/ui_base.gyp:ui_base', '../url/url.gyp:url_lib', - 'crx_file', 'update_client', ], 'include_dirs': [ '..', ], 'sources': [ - 'component_updater/background_downloader_win.cc', - 'component_updater/background_downloader_win.h', - 'component_updater/component_patcher.cc', - 'component_updater/component_patcher.h', - 'component_updater/component_patcher_operation.cc', - 'component_updater/component_patcher_operation.h', 'component_updater/component_updater_configurator.h', - 'component_updater/component_unpacker.cc', - 'component_updater/component_unpacker.h', 'component_updater/component_updater_paths.cc', 'component_updater/component_updater_paths.h', - 'component_updater/component_updater_ping_manager.cc', - 'component_updater/component_updater_ping_manager.h', 'component_updater/component_updater_service.cc', 'component_updater/component_updater_service.h', 'component_updater/component_updater_switches.cc', 'component_updater/component_updater_switches.h', - 'component_updater/component_updater_utils.cc', - 'component_updater/component_updater_utils.h', - 'component_updater/crx_update_item.h', - 'component_updater/crx_downloader.cc', - 'component_updater/crx_downloader.h', 'component_updater/default_component_installer.cc', 'component_updater/default_component_installer.h', 'component_updater/pref_names.cc', 'component_updater/pref_names.h', - 'component_updater/request_sender.cc', - 'component_updater/request_sender.h', - 'component_updater/update_checker.cc', - 'component_updater/update_checker.h', - 'component_updater/update_response.cc', - 'component_updater/update_response.h', - 'component_updater/url_fetcher_downloader.cc', - 'component_updater/url_fetcher_downloader.h', - ], - }, - { - # GN version: //components/component_updater:test_support - 'target_name': 'component_updater_test_support', - 'type': 'static_library', - 'dependencies': [ - 'component_updater', - '../testing/gmock.gyp:gmock', - '../testing/gtest.gyp:gtest', - ], - 'sources': [ - 'component_updater/test/test_configurator.cc', - 'component_updater/test/test_configurator.h', - 'component_updater/test/test_installer.cc', - 'component_updater/test/test_installer.h', - 'component_updater/test/url_request_post_interceptor.cc', - 'component_updater/test/url_request_post_interceptor.h', ], }, ],
diff --git a/components/component_updater/BUILD.gn b/components/component_updater/BUILD.gn index 2f26cf6..41df316c 100644 --- a/components/component_updater/BUILD.gn +++ b/components/component_updater/BUILD.gn
@@ -4,96 +4,23 @@ source_set("component_updater") { sources = [ - "background_downloader_win.cc", - "background_downloader_win.h", - "component_patcher.cc", - "component_patcher.h", - "component_patcher_operation.cc", - "component_patcher_operation.h", "component_updater_configurator.h", - "component_unpacker.cc", - "component_unpacker.h", "component_updater_paths.cc", "component_updater_paths.h", - "component_updater_ping_manager.cc", - "component_updater_ping_manager.h", "component_updater_service.cc", "component_updater_service.h", "component_updater_switches.cc", "component_updater_switches.h", - "component_updater_utils.cc", - "component_updater_utils.h", - "crx_update_item.h", - "crx_downloader.cc", - "crx_downloader.h", "default_component_installer.cc", "default_component_installer.h", "pref_names.cc", "pref_names.h", - "request_sender.cc", - "request_sender.h", - "update_checker.cc", - "update_checker.h", - "update_response.cc", - "update_response.h", - "url_fetcher_downloader.cc", - "url_fetcher_downloader.h", ] deps = [ "//base", - "//components/crx_file", "//components/update_client", - "//courgette:courgette_lib", - "//crypto", - "//third_party/libxml", - "//third_party/zlib:zip", - "//net", "//ui/base", "//url", ] } - -source_set("test_support") { - testonly = true - sources = [ - "test/test_configurator.cc", - "test/test_configurator.h", - "test/test_installer.cc", - "test/test_installer.h", - "test/url_request_post_interceptor.cc", - "test/url_request_post_interceptor.h", - ] - - deps = [ - ":component_updater", - "//base", - "//net:test_support", - "//testing/gtest", - "//testing/gmock", - "//url", - ] -} - -source_set("unit_tests") { - testonly = true - sources = [ - "test/component_patcher_unittest.cc", - "test/component_updater_ping_manager_unittest.cc", - "test/crx_downloader_unittest.cc", - "test/request_sender_unittest.cc", - "test/update_checker_unittest.cc", - "test/update_response_unittest.cc", - ] - - deps = [ - ":component_updater", - ":test_support", - "//base", - "//courgette:courgette_lib", - "//net:test_support", - "//testing/gtest", - "//testing/gmock", - "//third_party/libxml", - ] -}
diff --git a/components/component_updater/DEPS b/components/component_updater/DEPS index df47cfc..bfdab37 100644 --- a/components/component_updater/DEPS +++ b/components/component_updater/DEPS
@@ -1,11 +1,5 @@ include_rules = [ - "+components/crx_file", "+components/update_client", - "+courgette", - "+crypto", - "+libxml", - "+net", - "+third_party/libxml", - "+third_party/zlib", "+ui", + "+url", ]
diff --git a/components/component_updater/component_updater_service.cc b/components/component_updater/component_updater_service.cc index 92f13814..4b97bae 100644 --- a/components/component_updater/component_updater_service.cc +++ b/components/component_updater/component_updater_service.cc
@@ -25,17 +25,28 @@ #include "base/threading/sequenced_worker_pool.h" #include "base/threading/thread_checker.h" #include "base/timer/timer.h" -#include "components/component_updater/component_patcher_operation.h" -#include "components/component_updater/component_unpacker.h" -#include "components/component_updater/component_updater_configurator.h" -#include "components/component_updater/component_updater_ping_manager.h" -#include "components/component_updater/component_updater_utils.h" -#include "components/component_updater/crx_downloader.h" -#include "components/component_updater/crx_update_item.h" -#include "components/component_updater/update_checker.h" -#include "components/component_updater/update_response.h" +#include "components/update_client/component_patcher_operation.h" +#include "components/update_client/component_unpacker.h" +#include "components/update_client/configurator.h" +#include "components/update_client/crx_downloader.h" +#include "components/update_client/crx_update_item.h" +#include "components/update_client/ping_manager.h" +#include "components/update_client/update_checker.h" +#include "components/update_client/update_client.h" +#include "components/update_client/update_response.h" +#include "components/update_client/utils.h" #include "url/gurl.h" +using update_client::ComponentInstaller; +using update_client::ComponentUnpacker; +using update_client::Configurator; +using update_client::CrxComponent; +using update_client::CrxDownloader; +using update_client::CrxUpdateItem; +using update_client::PingManager; +using update_client::UpdateChecker; +using update_client::UpdateResponse; + namespace component_updater { // The component updater is designed to live until process shutdown, so @@ -65,28 +76,6 @@ } // namespace -CrxUpdateItem::CrxUpdateItem() - : status(kNew), - on_demand(false), - diff_update_failed(false), - error_category(0), - error_code(0), - extra_code1(0), - diff_error_category(0), - diff_error_code(0), - diff_extra_code1(0) { -} - -CrxUpdateItem::~CrxUpdateItem() { -} - -CrxComponent::CrxComponent() - : installer(NULL), allow_background_download(true) { -} - -CrxComponent::~CrxComponent() { -} - ////////////////////////////////////////////////////////////////////////////// // The one and only implementation of the ComponentUpdateService interface. In // charge of running the show. The main method is ProcessPendingItems() which @@ -869,7 +858,7 @@ const base::FilePath& crx_path, ComponentUnpacker::Error error, int extended_error) { - if (!DeleteFileAndEmptyParentDirectory(crx_path)) + if (!update_client::DeleteFileAndEmptyParentDirectory(crx_path)) NOTREACHED() << crx_path.value(); main_task_runner_->PostDelayedTask( FROM_HERE,
diff --git a/components/component_updater/component_updater_service.h b/components/component_updater/component_updater_service.h index b418e2d..5670619 100644 --- a/components/component_updater/component_updater_service.h +++ b/components/component_updater/component_updater_service.h
@@ -24,70 +24,26 @@ class SequencedTaskRunner; } +namespace content { +class ResourceThrottle; +} + namespace net { class URLRequestContextGetter; class URLRequest; } -namespace content { -class ResourceThrottle; +namespace update_client { +class ComponentInstaller; +class Configurator; +struct CrxComponent; +struct CrxUpdateItem; } namespace component_updater { -class Configurator; class OnDemandUpdater; -// Component specific installers must derive from this class and implement -// OnUpdateError() and Install(). A valid instance of this class must be -// given to ComponentUpdateService::RegisterComponent(). -class ComponentInstaller { - public: - // Called by the component updater on the main thread when there was a - // problem unpacking or verifying the component. |error| is a non-zero - // value which is only meaningful to the component updater. - virtual void OnUpdateError(int error) = 0; - - // Called by the component updater when a component has been unpacked - // and is ready to be installed. |manifest| contains the CRX manifest - // json dictionary and |unpack_path| contains the temporary directory - // with all the unpacked CRX files. This method may be called from - // a thread other than the main thread. - virtual bool Install(const base::DictionaryValue& manifest, - const base::FilePath& unpack_path) = 0; - - // Set |installed_file| to the full path to the installed |file|. |file| is - // the filename of the file in this component's CRX. Returns false if this is - // not possible (the file has been removed or modified, or its current - // location is unknown). Otherwise, returns true. - virtual bool GetInstalledFile(const std::string& file, - base::FilePath* installed_file) = 0; - - virtual ~ComponentInstaller() {} -}; - -// Describes a particular component that can be installed or updated. This -// structure is required to register a component with the component updater. -// |pk_hash| is the SHA256 hash of the component's public key. If the component -// is to be installed then version should be "0" or "0.0", else it should be -// the current version. |fingerprint|, and |name| are optional. -// |allow_background_download| specifies that the component can be background -// downloaded in some cases. The default for this value is |true| and the value -// can be overriden at the registration time. This is a temporary change until -// the issue 340448 is resolved. -struct CrxComponent { - std::vector<uint8_t> pk_hash; - ComponentInstaller* installer; - Version version; - std::string fingerprint; - std::string name; - bool allow_background_download; - CrxComponent(); - ~CrxComponent(); -}; - -struct CrxUpdateItem; - // The component update service is in charge of installing or upgrading // select parts of chrome. Each part is called a component and managed by // instances of CrxComponent registered using RegisterComponent(). On the @@ -165,7 +121,8 @@ // Add component to be checked for updates. You can call this method // before calling Start(). - virtual Status RegisterComponent(const CrxComponent& component) = 0; + virtual Status RegisterComponent( + const update_client::CrxComponent& component) = 0; // Returns a list of registered components. virtual std::vector<std::string> GetComponentIDs() const = 0; @@ -197,8 +154,9 @@ private: // Returns details about registered component in the |item| parameter. The // function returns true in case of success and false in case of errors. - virtual bool GetComponentDetails(const std::string& component_id, - CrxUpdateItem* item) const = 0; + virtual bool GetComponentDetails( + const std::string& component_id, + update_client::CrxUpdateItem* item) const = 0; friend class ::ComponentsUI; }; @@ -226,7 +184,8 @@ // Creates the component updater. You must pass a valid |config| allocated on // the heap which the component updater will own. -ComponentUpdateService* ComponentUpdateServiceFactory(Configurator* config); +ComponentUpdateService* ComponentUpdateServiceFactory( + update_client::Configurator* config); } // namespace component_updater
diff --git a/components/component_updater/default_component_installer.cc b/components/component_updater/default_component_installer.cc index 526b864..65889732 100644 --- a/components/component_updater/default_component_installer.cc +++ b/components/component_updater/default_component_installer.cc
@@ -14,9 +14,12 @@ #include "base/values.h" #include "base/version.h" // TODO(ddorwin): Find a better place for ReadManifest. -#include "components/component_updater/component_unpacker.h" -#include "components/component_updater/component_updater_configurator.h" +#include "components/component_updater/component_updater_service.h" #include "components/component_updater/default_component_installer.h" +#include "components/update_client/component_unpacker.h" +#include "components/update_client/update_client.h" + +using update_client::CrxComponent; namespace component_updater { @@ -155,7 +158,8 @@ continue; } - scoped_ptr<base::DictionaryValue> manifest = ReadManifest(path); + scoped_ptr<base::DictionaryValue> manifest = + update_client::ReadManifest(path); if (!manifest || !installer_traits_->VerifyInstallation(*manifest, path)) { DLOG(ERROR) << "Failed to read manifest or verify installation for " << installer_traits_->GetName() << " ("
diff --git a/components/component_updater/default_component_installer.h b/components/component_updater/default_component_installer.h index 3946ab39..120d3a5 100644 --- a/components/component_updater/default_component_installer.h +++ b/components/component_updater/default_component_installer.h
@@ -16,7 +16,7 @@ #include "base/threading/thread_checker.h" #include "base/values.h" #include "base/version.h" -#include "components/component_updater/component_updater_service.h" +#include "components/update_client/update_client.h" namespace base { class FilePath; @@ -26,6 +26,8 @@ namespace component_updater { +class ComponentUpdateService; + // Components should use a DefaultComponentInstaller by defining a class that // implements the members of ComponentInstallerTraits, and then registering a // DefaultComponentInstaller that has been constructed with an instance of that @@ -82,7 +84,7 @@ // A DefaultComponentInstaller is intended to be final, and not derived from. // Customization must be provided by passing a ComponentInstallerTraits object // to the constructor. -class DefaultComponentInstaller : public ComponentInstaller { +class DefaultComponentInstaller : public update_client::ComponentInstaller { public: DefaultComponentInstaller( scoped_ptr<ComponentInstallerTraits> installer_traits);
diff --git a/components/components_browsertests.isolate b/components/components_browsertests.isolate new file mode 100644 index 0000000..cb5b41c --- /dev/null +++ b/components/components_browsertests.isolate
@@ -0,0 +1,65 @@ +# Copyright 2015 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. +{ + 'includes': [ + '../base/base.isolate', + '../gin/v8.isolate', + ], + 'conditions': [ + ['OS=="linux" or OS=="mac" or OS=="win"', { + 'variables': { + 'files': [ + 'test/data/', + '../testing/test_env.py', + '<(PRODUCT_DIR)/components_browsertests<(EXECUTABLE_SUFFIX)', + '<(PRODUCT_DIR)/components_resources.pak', + '<(PRODUCT_DIR)/content_shell.pak', + ], + }, + }], + ['OS=="linux"', { + 'variables': { + 'command': [ + '../testing/xvfb.py', + '<(PRODUCT_DIR)', + '<(PRODUCT_DIR)/components_browsertests', + '--brave-new-test-launcher', + '--test-launcher-bot-mode', + '--asan=<(asan)', + '--lsan=<(lsan)', + ], + 'files': [ + '../testing/xvfb.py', + '<(PRODUCT_DIR)/libosmesa.so', + ], + }, + }], + ['OS=="linux" and use_ozone==0', { + 'variables': { + 'files': [ + '<(PRODUCT_DIR)/xdisplaycheck<(EXECUTABLE_SUFFIX)', + ], + }, + }], + ['OS=="mac" or OS=="win"', { + 'variables': { + 'command': [ + '../testing/test_env.py', + '<(PRODUCT_DIR)/components_browsertests<(EXECUTABLE_SUFFIX)', + '--brave-new-test-launcher', + '--test-launcher-bot-mode', + '--asan=<(asan)', + '--lsan=<(lsan)', + ], + }, + }], + ['OS=="mac"', { + 'variables': { + 'files': [ + '<(PRODUCT_DIR)/Content Shell.app/', + ], + }, + }], + ], +}
diff --git a/components/components_tests.gyp b/components/components_tests.gyp index 0c6f952..50585a6 100644 --- a/components/components_tests.gyp +++ b/components/components_tests.gyp
@@ -81,12 +81,6 @@ 'captive_portal/captive_portal_detector_unittest.cc', 'cloud_devices/common/cloud_devices_urls_unittest.cc', 'cloud_devices/common/printer_description_unittest.cc', - 'component_updater/test/component_patcher_unittest.cc', - 'component_updater/test/component_updater_ping_manager_unittest.cc', - 'component_updater/test/crx_downloader_unittest.cc', - 'component_updater/test/request_sender_unittest.cc', - 'component_updater/test/update_checker_unittest.cc', - 'component_updater/test/update_response_unittest.cc', 'content_settings/core/browser/content_settings_mock_provider.cc', 'content_settings/core/browser/content_settings_mock_provider.h', 'content_settings/core/browser/content_settings_provider_unittest.cc', @@ -99,6 +93,7 @@ 'data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol_unittest.cc', 'data_reduction_proxy/core/browser/data_reduction_proxy_configurator_unittest.cc', 'data_reduction_proxy/core/browser/data_reduction_proxy_interceptor_unittest.cc', + 'data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc', 'data_reduction_proxy/core/browser/data_reduction_proxy_metrics_unittest.cc', 'data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc', 'data_reduction_proxy/core/browser/data_reduction_proxy_prefs_unittest.cc', @@ -282,6 +277,12 @@ 'translate/ios/browser/language_detection_controller_unittest.mm', 'translate/ios/browser/translate_controller_unittest.mm', 'ui/zoom/page_zoom_unittests.cc', + 'update_client/test/component_patcher_unittest.cc', + 'update_client/test/crx_downloader_unittest.cc', + 'update_client/test/ping_manager_unittest.cc', + 'update_client/test/request_sender_unittest.cc', + 'update_client/test/update_checker_unittest.cc', + 'update_client/test/update_response_unittest.cc', 'update_client/update_query_params_unittest.cc', 'url_matcher/regex_set_matcher_unittest.cc', 'url_matcher/string_pattern_unittest.cc', @@ -310,211 +311,111 @@ '..', ], 'dependencies': [ + '../base/base.gyp:base', '../base/base.gyp:base_prefs_test_support', '../base/base.gyp:test_support_base', # TODO(blundell): Eliminate the need for this dependency in code # that iOS shares. crbug.com/325243 '../content/content_shell_and_tests.gyp:test_support_content', + '../google_apis/google_apis.gyp:google_apis_test_support', + '../jingle/jingle.gyp:notifier_test_util', + '../net/net.gyp:net_test_support', '../sql/sql.gyp:test_support_sql', '../sync/sync.gyp:sync', '../sync/sync.gyp:test_support_sync_api', '../testing/gmock.gyp:gmock', '../testing/gtest.gyp:gtest', + '../third_party/leveldatabase/leveldatabase.gyp:leveldatabase', + '../third_party/libaddressinput/libaddressinput.gyp:libaddressinput_util', + '../third_party/libjingle/libjingle.gyp:libjingle', + '../third_party/libphonenumber/libphonenumber.gyp:libphonenumber', + '../third_party/libxml/libxml.gyp:libxml', + '../third_party/protobuf/protobuf.gyp:protobuf_lite', '../ui/base/ui_base.gyp:ui_base', '../ui/gfx/gfx.gyp:gfx', '../ui/gfx/gfx.gyp:gfx_test_support', '../ui/resources/ui_resources.gyp:ui_resources', '../ui/strings/ui_strings.gyp:ui_strings', - - 'components_resources.gyp:components_resources', - - # Dependencies of auto_login_parser + '../url/url.gyp:url_lib', 'components.gyp:auto_login_parser', - - # Dependencies of autofill 'components.gyp:autofill_core_browser', 'components.gyp:autofill_core_common', 'components.gyp:autofill_core_test_support', - 'components_strings.gyp:components_strings', - '../third_party/libphonenumber/libphonenumber.gyp:libphonenumber', - '../third_party/libaddressinput/libaddressinput.gyp:libaddressinput_util', - - # Dependencies of bookmarks 'components.gyp:bookmarks_browser', 'components.gyp:bookmarks_test_support', - - # Dependencies of captive_portal 'components.gyp:captive_portal_test_support', - '../net/net.gyp:net_test_support', - - # Dependencies of cloud_devices 'components.gyp:cloud_devices_common', - - # Dependencies of component_updater - 'components.gyp:component_updater', - 'components.gyp:component_updater_test_support', - '../third_party/libxml/libxml.gyp:libxml', - - # Dependencies of content_settings 'components.gyp:content_settings_core_browser', 'components.gyp:content_settings_core_common', 'components.gyp:content_settings_core_test_support', - - # Dependencies of packed CT EV white list - 'components.gyp:packed_ct_ev_whitelist', - - # Dependencies of crash 'components.gyp:crash_test_support', - - # Dependencies of crx_file 'components.gyp:crx_file', - - # Dependencies of data_reduction_proxy 'components.gyp:data_reduction_proxy_core_browser', 'components.gyp:data_reduction_proxy_core_common', 'components.gyp:data_reduction_proxy_test_support', - - # Dependencies of dom_distiller 'components.gyp:distilled_page_proto', 'components.gyp:dom_distiller_core', 'components.gyp:dom_distiller_test_support', - - # Dependencies of domain_reliability 'components.gyp:domain_reliability', - - # Dependencies of enhanced_bookmarks 'components.gyp:enhanced_bookmarks', 'components.gyp:enhanced_bookmarks_test_support', - - # Dependencies of favicon_base 'components.gyp:favicon_base', - - # Dependencies of feedback 'components.gyp:feedback_component', - - # Dependencies of gcm 'components.gyp:gcm_driver', 'components.gyp:gcm_driver_test_support', - - # Dependencies of google 'components.gyp:google_core_browser', - - # Dependencies of history 'components.gyp:history_core_browser', 'components.gyp:history_core_common', - - # Dependencies of invalidation 'components.gyp:invalidation', 'components.gyp:invalidation_test_support', - '../jingle/jingle.gyp:notifier_test_util', - '../third_party/libjingle/libjingle.gyp:libjingle', - - # Dependencies of json_schema 'components.gyp:json_schema', - - # Dependencies of keyed_service 'components.gyp:keyed_service_core', - - # Dependencies of language_usage_metrics 'components.gyp:language_usage_metrics', - - # Dependencies of leveldb_proto - '../third_party/leveldatabase/leveldatabase.gyp:leveldatabase', 'components.gyp:leveldb_proto', 'components.gyp:leveldb_proto_test_support', - - # Dependencies of login 'components.gyp:login', - - # Dependencies of metrics 'components.gyp:metrics', 'components.gyp:metrics_gpu', 'components.gyp:metrics_net', 'components.gyp:metrics_profiler', 'components.gyp:metrics_test_support', - - # Dependencies of network_time 'components.gyp:network_time', - - # Dependencies of omnibox 'components.gyp:omnibox', 'components.gyp:omnibox_test_support', - - # Dependencies of os_crypt 'components.gyp:os_crypt', - - # Dependencies of ownership 'components.gyp:ownership', - - # Dependencies of password_manager + 'components.gyp:packed_ct_ev_whitelist', + 'components.gyp:password_manager_core_browser', 'components.gyp:password_manager_core_browser', 'components.gyp:password_manager_core_browser_test_support', - - # Dependencies of precache/core - 'components.gyp:password_manager_core_browser', 'components.gyp:precache_core', - - # Dependencies of pref_registry 'components.gyp:pref_registry_test_support', - - # Dependencies of query_parser 'components.gyp:query_parser', - - # Dependencies of rappor 'components.gyp:rappor', 'components.gyp:rappor_test_support', - - # Dependencies of search 'components.gyp:search', - - # Dependencies of search_engines 'components.gyp:search_engines', 'components.gyp:search_engines_test_support', - - # Dependencies of search_provider_logos 'components.gyp:search_provider_logos', - - # Dependencies of sessions - '../third_party/protobuf/protobuf.gyp:protobuf_lite', 'components.gyp:sessions_test_support', - - # Dependencies of signin 'components.gyp:signin_core_browser', 'components.gyp:signin_core_browser_test_support', - '../google_apis/google_apis.gyp:google_apis_test_support', - - # Dependencies of suggestions 'components.gyp:suggestions', - - # Dependencies of sync_driver 'components.gyp:sync_driver_test_support', - - # Dependencies of translate. 'components.gyp:translate_core_browser', 'components.gyp:translate_core_common', 'components.gyp:translate_core_language_detection', - - # Dependencies of wallpaper - 'components.gyp:wallpaper', - - # Dependencies of ui/zoom 'components.gyp:ui_zoom', - - # Dependencies of update_client 'components.gyp:update_client', - - # Dependencies of url_fixer + 'components.gyp:update_client_test_support', 'components.gyp:url_fixer', - '../url/url.gyp:url_lib', - - # Dependencies of variations 'components.gyp:variations', 'components.gyp:variations_http_provider', - - # Dependencies of web_resource + 'components.gyp:wallpaper', 'components.gyp:web_resource', 'components.gyp:web_resource_test_support', - '../base/base.gyp:base', + 'components_resources.gyp:components_resources', + 'components_strings.gyp:components_strings', ], 'actions': [ { @@ -844,6 +745,7 @@ 'pairing/message_buffer_unittest.cc', 'timers/alarm_timer_unittest.cc', 'wifi_sync/wifi_config_delegate_chromeos_unittest.cc', + 'wifi_sync/wifi_credential_syncable_service_unittest.cc', 'wifi_sync/wifi_credential_unittest.cc', 'wifi_sync/wifi_security_class_chromeos_unittest.cc', 'wifi_sync/wifi_security_class_unittest.cc', @@ -852,7 +754,7 @@ 'storage_monitor/storage_monitor_linux_unittest.cc', ], 'dependencies': [ - # Dependencies of wifi_sync + # Dependencies of wifi_sync 'components.gyp:wifi_sync', 'components.gyp:pairing', @@ -1039,6 +941,30 @@ ], }], ['OS!="ios"', { + 'conditions': [ + ['test_isolation_mode != "noop"', { + 'targets': [ + { + 'target_name': 'components_browsertests_run', + 'type': 'none', + 'dependencies': [ 'components_browsertests' ], + 'includes': [ + '../build/isolate.gypi', + ], + 'sources': [ + 'components_browsertests.isolate', + ], + 'conditions': [ + ['use_x11==1', { + 'dependencies': [ + '../tools/xdisplaycheck/xdisplaycheck.gyp:xdisplaycheck', + ], + }], + ], + }, + ], + }], + ], 'targets': [ { 'target_name': 'components_browsertests', @@ -1146,6 +1072,11 @@ '../base/allocator/allocator.gyp:allocator', ], }], + ['OS=="mac"', { + 'dependencies': [ + '../content/content_shell_and_tests.gyp:content_shell', # Needed for Content Shell.app's Helper. + ], + }], ], }, ],
diff --git a/components/crash/app/breakpad_linux.cc b/components/crash/app/breakpad_linux.cc index 09a9251..a925e07 100644 --- a/components/crash/app/breakpad_linux.cc +++ b/components/crash/app/breakpad_linux.cc
@@ -401,25 +401,25 @@ public: explicit CrashReporterWriter(int fd); - virtual void AddBoundary() override; + void AddBoundary() override; - virtual void AddEnd() override; + void AddEnd() override; - virtual void AddPairData(const char* msg_type, + void AddPairData(const char* msg_type, + size_t msg_type_size, + const char* msg_data, + size_t msg_data_size) override; + + void AddPairDataInChunks(const char* msg_type, size_t msg_type_size, - const char* msg_data, - size_t msg_data_size) override; + const char* msg_data, + size_t msg_data_size, + size_t chunk_size, + bool strip_trailing_spaces) override; - virtual void AddPairDataInChunks(const char* msg_type, - size_t msg_type_size, - const char* msg_data, - size_t msg_data_size, - size_t chunk_size, - bool strip_trailing_spaces) override; - - virtual void AddFileContents(const char* filename_msg, - uint8_t* file_data, - size_t file_size) override; + void AddFileContents(const char* filename_msg, + uint8_t* file_data, + size_t file_size) override; private: DISALLOW_COPY_AND_ASSIGN(CrashReporterWriter);
diff --git a/components/data_reduction_proxy.gypi b/components/data_reduction_proxy.gypi index afa026df..5cd2834 100644 --- a/components/data_reduction_proxy.gypi +++ b/components/data_reduction_proxy.gypi
@@ -40,6 +40,8 @@ 'data_reduction_proxy/core/browser/data_reduction_proxy_delegate.h', 'data_reduction_proxy/core/browser/data_reduction_proxy_interceptor.cc', 'data_reduction_proxy/core/browser/data_reduction_proxy_interceptor.h', + 'data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc', + 'data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h', 'data_reduction_proxy/core/browser/data_reduction_proxy_metrics.cc', 'data_reduction_proxy/core/browser/data_reduction_proxy_metrics.h', 'data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc',
diff --git a/components/data_reduction_proxy/core/browser/BUILD.gn b/components/data_reduction_proxy/core/browser/BUILD.gn index 5b87ff2..f014d0ff 100644 --- a/components/data_reduction_proxy/core/browser/BUILD.gn +++ b/components/data_reduction_proxy/core/browser/BUILD.gn
@@ -14,6 +14,8 @@ "data_reduction_proxy_delegate.h", "data_reduction_proxy_interceptor.cc", "data_reduction_proxy_interceptor.h", + "data_reduction_proxy_io_data.cc", + "data_reduction_proxy_io_data.h", "data_reduction_proxy_metrics.cc", "data_reduction_proxy_metrics.h", "data_reduction_proxy_network_delegate.cc",
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol_unittest.cc index 19d3cf2..157f0d8 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol_unittest.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol_unittest.cc
@@ -14,6 +14,7 @@ #include "base/run_loop.h" #include "base/strings/stringprintf.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_interceptor.h" +#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_usage_stats.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_event_store.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h" @@ -79,14 +80,9 @@ class DataReductionProxyProtocolTest : public testing::Test { public: DataReductionProxyProtocolTest() : http_user_agent_settings_("", "") { - proxy_params_.reset( - new TestDataReductionProxyParams( - DataReductionProxyParams::kAllowed | - DataReductionProxyParams::kFallbackAllowed | - DataReductionProxyParams::kPromoAllowed, - TestDataReductionProxyParams::HAS_EVERYTHING & - ~TestDataReductionProxyParams::HAS_DEV_ORIGIN & - ~TestDataReductionProxyParams::HAS_DEV_FALLBACK_ORIGIN)); + settings_.reset( + new DataReductionProxySettings(CreateTestDataReductionProxyParams())); + proxy_params_.reset(CreateTestDataReductionProxyParams()); simple_interceptor_.reset(new SimpleURLRequestInterceptor()); net::URLRequestFilter::GetInstance()->AddHostnameInterceptor( "http", "www.google.com", simple_interceptor_.Pass()); @@ -98,6 +94,16 @@ base::RunLoop().RunUntilIdle(); } + TestDataReductionProxyParams* CreateTestDataReductionProxyParams() { + return new TestDataReductionProxyParams( + DataReductionProxyParams::kAllowed | + DataReductionProxyParams::kFallbackAllowed | + DataReductionProxyParams::kPromoAllowed, + TestDataReductionProxyParams::HAS_EVERYTHING & + ~TestDataReductionProxyParams::HAS_DEV_ORIGIN & + ~TestDataReductionProxyParams::HAS_DEV_FALLBACK_ORIGIN); + } + void SetUp() override { network_change_notifier_.reset(net::NetworkChangeNotifier::CreateMock()); net::NetworkChangeNotifier::SetTestNotificationsOnly(true); @@ -118,13 +124,14 @@ // to requests. context_->set_http_user_agent_settings(&http_user_agent_settings_); usage_stats_.reset(new DataReductionProxyUsageStats( - proxy_params_.get(), base::MessageLoopProxy::current())); + settings_->params(), settings_.get(), + base::MessageLoopProxy::current())); event_store_.reset( new DataReductionProxyEventStore(base::MessageLoopProxy::current())); DataReductionProxyInterceptor* interceptor = new DataReductionProxyInterceptor( - proxy_params_.get(), usage_stats_.get(), event_store_.get()); + settings_->params(), usage_stats_.get(), event_store_.get()); scoped_ptr<net::URLRequestJobFactoryImpl> job_factory_impl( new net::URLRequestJobFactoryImpl()); job_factory_.reset(new net::URLRequestInterceptingJobFactory( @@ -330,6 +337,7 @@ scoped_ptr<net::TestNetworkDelegate> network_delegate_; scoped_ptr<ProxyService> proxy_service_; scoped_ptr<TestDataReductionProxyParams> proxy_params_; + scoped_ptr<DataReductionProxySettings> settings_; scoped_ptr<DataReductionProxyUsageStats> usage_stats_; scoped_ptr<DataReductionProxyEventStore> event_store_; net::StaticHttpUserAgentSettings http_user_agent_settings_;
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_interceptor_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_interceptor_unittest.cc index 09ae8048..d577fcee 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_interceptor_unittest.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_interceptor_unittest.cc
@@ -9,7 +9,9 @@ #include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h" -#include "components/data_reduction_proxy/core/common/data_reduction_proxy_event_store.h" +#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_auth_request_handler.h" +#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h" +#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params_test_utils.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h" @@ -161,6 +163,7 @@ } ~DataReductionProxyInterceptorWithServerTest() override { + io_data_->ShutdownOnUIThread(); // URLRequestJobs may post clean-up tasks on destruction. base::RunLoop().RunUntilIdle(); } @@ -177,39 +180,43 @@ ASSERT_TRUE(proxy_.InitializeAndWaitUntilReady()); ASSERT_TRUE(direct_.InitializeAndWaitUntilReady()); - params_.reset( + // Owned by settings_. + TestDataReductionProxyParams* params = new TestDataReductionProxyParams( DataReductionProxyParams::kAllowed, TestDataReductionProxyParams::HAS_EVERYTHING & ~TestDataReductionProxyParams::HAS_DEV_ORIGIN & - ~TestDataReductionProxyParams::HAS_DEV_FALLBACK_ORIGIN)); - params_->set_origin(proxy_.GetURL("/")); + ~TestDataReductionProxyParams::HAS_DEV_FALLBACK_ORIGIN); + params->set_origin(proxy_.GetURL("/")); std::string proxy_name = - net::HostPortPair::FromURL(GURL(params_->origin())).ToString(); + net::HostPortPair::FromURL(GURL(params->origin())).ToString(); proxy_service_.reset( net::ProxyService::CreateFixedFromPacResult( "PROXY " + proxy_name + "; DIRECT")); context_.set_proxy_service(proxy_service_.get()); - event_store_.reset( - new DataReductionProxyEventStore(loop_.message_loop_proxy())); - - DataReductionProxyInterceptor* interceptor = - new DataReductionProxyInterceptor(params_.get(), NULL, - event_store_.get()); + settings_.reset(new DataReductionProxySettings(params)); + io_data_.reset( + new DataReductionProxyIOData( + data_reduction_proxy::Client::UNKNOWN, + scoped_ptr< + data_reduction_proxy::DataReductionProxyStatisticsPrefs>(), + settings_.get(), + &net_log_, + loop_.message_loop_proxy(), + loop_.message_loop_proxy())); scoped_ptr<net::URLRequestJobFactoryImpl> job_factory_impl( new net::URLRequestJobFactoryImpl()); job_factory_.reset( new net::URLRequestInterceptingJobFactory( job_factory_impl.Pass(), - make_scoped_ptr(interceptor))); + io_data_->CreateInterceptor())); context_.set_job_factory(job_factory_.get()); context_.Init(); } - const net::TestURLRequestContext& context() { return context_; } @@ -219,18 +226,16 @@ } private: + base::MessageLoopForIO loop_; net::CapturingNetLog net_log_; net::TestNetworkDelegate network_delegate_; - net::TestURLRequestContext context_; net::test_server::EmbeddedTestServer proxy_; net::test_server::EmbeddedTestServer direct_; - scoped_ptr<TestDataReductionProxyParams> params_; scoped_ptr<net::ProxyService> proxy_service_; - scoped_ptr<DataReductionProxyEventStore> event_store_; scoped_ptr<net::URLRequestJobFactory> job_factory_; - - base::MessageLoopForIO loop_; + scoped_ptr<DataReductionProxySettings> settings_; + scoped_ptr<DataReductionProxyIOData> io_data_; }; TEST_F(DataReductionProxyInterceptorWithServerTest, TestBypass) {
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc new file mode 100644 index 0000000..71d206e2 --- /dev/null +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc
@@ -0,0 +1,119 @@ +// Copyright 2015 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/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h" + +#include "base/bind.h" +#include "base/command_line.h" +#include "base/prefs/pref_member.h" +#include "base/single_thread_task_runner.h" +#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_auth_request_handler.h" +#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol.h" +#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.h" +#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.h" +#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_interceptor.h" +#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.h" +#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h" +#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_usage_stats.h" +#include "components/data_reduction_proxy/core/common/data_reduction_proxy_event_store.h" +#include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h" +#include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h" +#include "net/base/net_log.h" + +namespace data_reduction_proxy { + +DataReductionProxyIOData::DataReductionProxyIOData( + const Client& client, + scoped_ptr<DataReductionProxyStatisticsPrefs> statistics_prefs, + DataReductionProxySettings* settings, + net::NetLog* net_log, + scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) + : client_(client), + statistics_prefs_(statistics_prefs.Pass()), + settings_(settings), + net_log_(net_log), + io_task_runner_(io_task_runner), + ui_task_runner_(ui_task_runner), + shutdown_on_ui_(false) { + DCHECK(settings); + DCHECK(net_log); + DCHECK(io_task_runner_.get()); + DCHECK(ui_task_runner_.get()); + params_ = settings->params()->Clone(); + auth_request_handler_.reset(new DataReductionProxyAuthRequestHandler( + client_, params_.get(), io_task_runner_)); + event_store_.reset(new DataReductionProxyEventStore(ui_task_runner)); + configurator_.reset(new DataReductionProxyConfigurator( + io_task_runner, net_log, event_store_.get())); + proxy_delegate_.reset( + new data_reduction_proxy::DataReductionProxyDelegate( + auth_request_handler_.get(), params_.get())); +} + +DataReductionProxyIOData::~DataReductionProxyIOData() { + DCHECK(shutdown_on_ui_); +} + +void DataReductionProxyIOData::InitOnUIThread(PrefService* pref_service) { + DCHECK(ui_task_runner_->BelongsToCurrentThread()); + enabled_.Init(prefs::kDataReductionProxyEnabled, pref_service); + enabled_.MoveToThread(io_task_runner_); +} + +void DataReductionProxyIOData::ShutdownOnUIThread() { + DCHECK(!shutdown_on_ui_); + DCHECK(ui_task_runner_->BelongsToCurrentThread()); + if (statistics_prefs_) { + statistics_prefs_->WritePrefs(); + statistics_prefs_->ShutdownOnUIThread(); + } + enabled_.Destroy(); + shutdown_on_ui_ = true; +} + +bool DataReductionProxyIOData::IsEnabled() const { + DCHECK(io_task_runner_->BelongsToCurrentThread()); + return enabled_.GetValue() || + base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableDataReductionProxy); +} + +scoped_ptr<net::URLRequestInterceptor> +DataReductionProxyIOData::CreateInterceptor() { + DCHECK(io_task_runner_->BelongsToCurrentThread()); + return make_scoped_ptr(new DataReductionProxyInterceptor( + params_.get(), usage_stats_.get(), event_store_.get())); +} + +void DataReductionProxyIOData::EnableCompressionStatisticsLogging( + PrefService* prefs, + const base::TimeDelta& commit_delay) { + DCHECK(ui_task_runner_->BelongsToCurrentThread()); + statistics_prefs_.reset( + new DataReductionProxyStatisticsPrefs( + prefs, ui_task_runner_, commit_delay)); +} + +scoped_ptr<DataReductionProxyNetworkDelegate> +DataReductionProxyIOData::CreateNetworkDelegate( + scoped_ptr<net::NetworkDelegate> wrapped_network_delegate, + bool track_proxy_bypass_statistics) { + DCHECK(io_task_runner_->BelongsToCurrentThread()); + scoped_ptr<DataReductionProxyNetworkDelegate> network_delegate( + new DataReductionProxyNetworkDelegate( + wrapped_network_delegate.Pass(), params_.get(), + auth_request_handler_.get(), configurator_.get())); + if (track_proxy_bypass_statistics && !usage_stats_) { + usage_stats_.reset( + new data_reduction_proxy::DataReductionProxyUsageStats( + params_.get(), settings_, ui_task_runner_)); + network_delegate->InitStatisticsPrefsAndUMA( + ui_task_runner_, statistics_prefs_.get(), &enabled_, + usage_stats_.get()); + } + return network_delegate.Pass(); +} + +} // namespace data_reduction_proxy
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h new file mode 100644 index 0000000..b679892 --- /dev/null +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h
@@ -0,0 +1,149 @@ +// Copyright 2015 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_DATA_REDUCTION_PROXY_CORE_BROWSER_DATA_REDUCTION_PROXY_IO_DATA_H_ +#define COMPONENTS_DATA_REDUCTION_PROXY_CORE_BROWSER_DATA_REDUCTION_PROXY_IO_DATA_H_ + +#include "base/memory/scoped_ptr.h" +#include "base/prefs/pref_member.h" +#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_auth_request_handler.h" +#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.h" +#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.h" + +namespace net { +class NetLog; +class URLRequestInterceptor; +} + +namespace data_reduction_proxy { + +class DataReductionProxyConfigurator; +class DataReductionProxyEventStore; +class DataReductionProxyParams; +class DataReductionProxySettings; +class DataReductionProxyStatisticsPrefs; +class DataReductionProxyUsageStats; + +// Contains and initializes all Data Reduction Proxy objects that operate on +// the IO thread. +class DataReductionProxyIOData { + public: + // Constructs a DataReductionProxyIOData object and takes ownership of + // |params| and |statistics_prefs|. |params| contains information about the + // DNS names used by the proxy, and allowable configurations. + // |statistics_prefs| maintains compression statistics during use of the + // proxy. |settings| provides a UI hook to signal when the proxy is + // unavailable. Only |statistics_prefs.get()| may be null. + DataReductionProxyIOData( + const Client& client, + scoped_ptr<DataReductionProxyStatisticsPrefs> statistics_prefs, + DataReductionProxySettings* settings, + net::NetLog* net_log, + scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner); + + virtual ~DataReductionProxyIOData(); + + // Initializes preferences, including a preference to track whether the + // Data Reduction Proxy is enabled. + void InitOnUIThread(PrefService* pref_service); + + // Destroys the statistics preferences. + void ShutdownOnUIThread(); + + // Constructs statistics prefs. This is not necessary if a valid statistics + // prefs is passed into the constructor. + void EnableCompressionStatisticsLogging( + PrefService* prefs, + const base::TimeDelta& commit_delay); + + // Creates an interceptor suitable for following the Data Reduction Proxy + // bypass protocol. + scoped_ptr<net::URLRequestInterceptor> CreateInterceptor(); + + // Creates a NetworkDelegate suitable for carrying out the Data Reduction + // Proxy protocol, including authenticating, establishing a handler to + // override the current proxy configuration, and + // gathering statistics for UMA. + scoped_ptr<DataReductionProxyNetworkDelegate> CreateNetworkDelegate( + scoped_ptr<net::NetworkDelegate> wrapped_network_delegate, + bool track_proxy_bypass_statistics); + + // Returns true if the Data Reduction Proxy is enabled and false otherwise. + bool IsEnabled() const; + + DataReductionProxyConfigurator* configurator() const { + return configurator_.get(); + } + + DataReductionProxyEventStore* event_store() const { + return event_store_.get(); + } + + DataReductionProxyStatisticsPrefs* statistics_prefs() const { + return statistics_prefs_.get(); + } + + net::ProxyDelegate* proxy_delegate() const { + return proxy_delegate_.get(); + } + + net::NetLog* net_log() { + return net_log_; + } + + // Used for testing. + DataReductionProxyUsageStats* usage_stats() const { + return usage_stats_.get(); + } + + private: + // The type of Data Reduction Proxy client. + Client client_; + + // Parameters including DNS names and allowable configurations. + scoped_ptr<DataReductionProxyParams> params_; + + // Tracker of compression statistics to be displayed to the user. + scoped_ptr<DataReductionProxyStatisticsPrefs> statistics_prefs_; + + // Tracker of Data Reduction Proxy-related events, e.g., for logging. + scoped_ptr<DataReductionProxyEventStore> event_store_; + + // Setter of the Data Reduction Proxy-specific proxy configuration. + scoped_ptr<DataReductionProxyConfigurator> configurator_; + + // A proxy delegate. Used, for example, to add authentication to HTTP CONNECT + // request. + scoped_ptr<DataReductionProxyDelegate> proxy_delegate_; + + // User-facing settings object. + DataReductionProxySettings* settings_; + + // Tracker of various metrics to be reported in UMA. + scoped_ptr<DataReductionProxyUsageStats> usage_stats_; + + // Constructs credentials suitable for authenticating the client. + scoped_ptr<DataReductionProxyAuthRequestHandler> auth_request_handler_; + + // A net log. + net::NetLog* net_log_; + + // IO and UI task runners, respectively. + scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; + scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_; + + // Used + bool shutdown_on_ui_; + + // Preference that determines if the Data Reduction Proxy has been enabled + // by the user. In practice, this can be overridden by the command line. + BooleanPrefMember enabled_; + + DISALLOW_COPY_AND_ASSIGN(DataReductionProxyIOData); +}; + +} // namespace data_reduction_proxy +#endif // COMPONENTS_DATA_REDUCTION_PROXY_CORE_BROWSER_DATA_REDUCTION_PROXY_IO_DATA_H_ +
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc new file mode 100644 index 0000000..8aa47d8 --- /dev/null +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc
@@ -0,0 +1,159 @@ +// Copyright 2015 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/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h" + +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/message_loop/message_loop.h" +#include "base/message_loop/message_loop_proxy.h" +#include "base/prefs/testing_pref_service.h" +#include "base/strings/string_number_conversions.h" +#include "base/time/time.h" +#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_auth_request_handler.h" +#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_prefs.h" +#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h" +#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_statistics_prefs.h" +#include "components/data_reduction_proxy/core/common/data_reduction_proxy_params_test_utils.h" +#include "net/base/net_log.h" +#include "net/url_request/url_request_interceptor.h" +#include "net/url_request/url_request_test_util.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +// Used only to verify that a wrapped network delegate gets called. +class CountingNetworkDelegate : public net::NetworkDelegateImpl { + public: + CountingNetworkDelegate() : created_requests_(0) { + } + + ~CountingNetworkDelegate() final { + } + + int OnBeforeURLRequest(net::URLRequest* request, + const net::CompletionCallback& callback, + GURL* new_url) final { + created_requests_++; + return net::OK; + } + + int created_requests() const { + return created_requests_; + } + + private: + int created_requests_; +}; + +} // namespace + +namespace data_reduction_proxy { + +class DataReductionProxyIODataTest : public testing::Test { + public: + void SetUp() override { + DataReductionProxyParams* params = + new TestDataReductionProxyParams( + TestDataReductionProxyParams::kAllowed, + TestDataReductionProxyParams::HAS_EVERYTHING & + ~TestDataReductionProxyParams::HAS_DEV_ORIGIN & + ~TestDataReductionProxyParams::HAS_DEV_FALLBACK_ORIGIN); + settings_.reset(new DataReductionProxySettings(params)); + RegisterSimpleProfilePrefs(prefs_.registry()); + } + + void RequestCallback(int err) { + } + + + scoped_refptr<base::MessageLoopProxy> message_loop_proxy() { + return loop_.message_loop_proxy(); + } + + net::TestDelegate* delegate() { + return &delegate_; + } + + const net::TestURLRequestContext& context() const { + return context_; + } + + net::NetLog* net_log() { + return &net_log_; + } + + PrefService* prefs() { + return &prefs_; + } + + DataReductionProxySettings* settings() const { + return settings_.get(); + } + + private: + base::MessageLoopForIO loop_; + net::TestDelegate delegate_; + net::TestURLRequestContext context_; + net::NetLog net_log_; + TestingPrefServiceSimple prefs_; + scoped_ptr<DataReductionProxySettings> settings_; +}; + +TEST_F(DataReductionProxyIODataTest, TestConstruction) { + DataReductionProxyStatisticsPrefs* statistics_prefs = + new DataReductionProxyStatisticsPrefs( + prefs(), message_loop_proxy(), base::TimeDelta()); + scoped_ptr<DataReductionProxyIOData> io_data( + new DataReductionProxyIOData( + Client::UNKNOWN, make_scoped_ptr(statistics_prefs), settings(), + net_log(), message_loop_proxy(), message_loop_proxy())); + + // Check that io_data creates an interceptor. Such an interceptor is + // thoroughly tested by DataReductionProxyInterceptoTest. + scoped_ptr<net::URLRequestInterceptor> interceptor = + io_data->CreateInterceptor(); + EXPECT_NE(nullptr, interceptor.get()); + + // At this point io_data->statistics_prefs() should be set and compression + // statistics logging should be enabled. + EXPECT_EQ(statistics_prefs, io_data->statistics_prefs()); + + // Check if explicitly enabling compression statistics logging results in + // a new logging object being created. + io_data->EnableCompressionStatisticsLogging(prefs(), base::TimeDelta()); + EXPECT_NE(statistics_prefs, io_data->statistics_prefs()); + EXPECT_TRUE(io_data->statistics_prefs()); + + // When creating a network delegate, expect that it properly wraps a + // network delegate. Such a network delegate is thoroughly tested by + // DataReductionProxyNetworkDelegateTest. + scoped_ptr<net::URLRequest> fake_request = + context().CreateRequest( + GURL("http://www.foo.com/"), net::IDLE, delegate(), NULL); + CountingNetworkDelegate* wrapped_network_delegate = + new CountingNetworkDelegate(); + scoped_ptr<DataReductionProxyNetworkDelegate> network_delegate = + io_data->CreateNetworkDelegate( + make_scoped_ptr(wrapped_network_delegate), false); + network_delegate->NotifyBeforeURLRequest( + fake_request.get(), + base::Bind(&DataReductionProxyIODataTest::RequestCallback, + base::Unretained(this)), nullptr); + EXPECT_EQ(1, wrapped_network_delegate->created_requests()); + EXPECT_EQ(nullptr, io_data->usage_stats()); + + // Creating a second delegate with bypass statistics tracking should result + // in usage stats being created. + io_data->CreateNetworkDelegate(make_scoped_ptr(new CountingNetworkDelegate()), + true); + EXPECT_NE(nullptr, io_data->usage_stats()); + + // The Data Reduction Proxy isn't actually enabled here. + io_data->InitOnUIThread(prefs()); + EXPECT_FALSE(io_data->IsEnabled()); + io_data->ShutdownOnUIThread(); +} + +} // namespace data_reduction_proxy
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc index 703b22c41..b925211f 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc
@@ -11,6 +11,7 @@ #include "base/strings/string_number_conversions.h" #include "base/time/time.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_auth_request_handler.h" +#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_statistics_prefs.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_usage_stats.h" #include "net/base/load_flags.h" @@ -74,7 +75,7 @@ scoped_ptr<net::NetworkDelegate> network_delegate, DataReductionProxyParams* params, DataReductionProxyAuthRequestHandler* handler, - const ProxyConfigGetter& getter) + const DataReductionProxyConfigurator* configurator) : LayeredNetworkDelegate(network_delegate.Pass()), ui_task_runner_(NULL), received_content_length_(0), @@ -84,7 +85,7 @@ data_reduction_proxy_usage_stats_(NULL), data_reduction_proxy_auth_request_handler_(handler), data_reduction_proxy_statistics_prefs_(NULL), - proxy_config_getter_(getter) { + configurator_(configurator) { DCHECK(data_reduction_proxy_params_); DCHECK(data_reduction_proxy_auth_request_handler_); } @@ -92,12 +93,6 @@ DataReductionProxyNetworkDelegate::~DataReductionProxyNetworkDelegate() { } -void DataReductionProxyNetworkDelegate::InitProxyConfigOverrider( - const OnResolveProxyHandler& proxy_handler) { - DCHECK(!proxy_config_getter_.is_null()); - on_resolve_proxy_handler_ = proxy_handler; -} - void DataReductionProxyNetworkDelegate::InitStatisticsPrefsAndUMA( scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, DataReductionProxyStatisticsPrefs* statistics_prefs, @@ -147,12 +142,9 @@ int load_flags, const net::ProxyService& proxy_service, net::ProxyInfo* result) { - // TODO(sclittle): Call OnResolveProxyHandler directly, see - // http://crbug.com/447346. - if (!on_resolve_proxy_handler_.is_null() && - !proxy_config_getter_.is_null()) { - on_resolve_proxy_handler_.Run( - url, load_flags, proxy_config_getter_.Run(), + if (configurator_) { + OnResolveProxyHandler( + url, load_flags, configurator_->GetProxyConfigOnIOThread(), proxy_service.proxy_retry_info(), data_reduction_proxy_params_, result); } } @@ -194,11 +186,10 @@ // specified with the Content-Length header, which may be inaccurate, // or missing, as is the case with chunked encoding. int64 received_content_length = request->received_response_content_length(); - if (!request->was_cached() && // Don't record cached content received_content_length && // Zero-byte responses aren't useful. (is_http || is_https) && // Only record for HTTP or HTTPS urls. - !proxy_config_getter_.is_null()) { // Used by request type and histograms. + configurator_) { // Used by request type and histograms. int64 original_content_length = request->response_info().headers->GetInt64HeaderValue( "x-original-content-length"); @@ -206,9 +197,10 @@ request->response_info().headers->GetFreshnessLifetimes( request->response_info().response_time).freshness; DataReductionProxyRequestType request_type = - GetDataReductionProxyRequestType(*request, - proxy_config_getter_.Run(), - *data_reduction_proxy_params_); + GetDataReductionProxyRequestType( + *request, + configurator_->GetProxyConfigOnIOThread(), + *data_reduction_proxy_params_); int64 adjusted_original_content_length = GetAdjustedOriginalContentLength(request_type, @@ -226,7 +218,7 @@ data_reduction_proxy_usage_stats_->RecordBytesHistograms( *request, *data_reduction_proxy_enabled_, - proxy_config_getter_.Run()); + configurator_->GetProxyConfigOnIOThread()); } DVLOG(2) << __FUNCTION__ << " received content length: " << received_content_length
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.h index 0744b86..7da1858e 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.h +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.h
@@ -38,6 +38,7 @@ namespace data_reduction_proxy { class DataReductionProxyAuthRequestHandler; +class DataReductionProxyConfigurator; class DataReductionProxyParams; class DataReductionProxyStatisticsPrefs; class DataReductionProxyUsageStats; @@ -46,20 +47,6 @@ // NetworkDelegate and adds Data Reduction Proxy specific logic. class DataReductionProxyNetworkDelegate : public net::LayeredNetworkDelegate { public: - // Provides an opportunity to interpose on proxy resolution. Called before - // ProxyService.ResolveProxy() returns. The Data Reduction Proxy's - // configuration is provided along with the resolution for this URL, in - // |result|, whch may be modified. Retry info is presumed to be from the proxy - // service. - // TODO(sclittle): Remove this, see http://crbug.com/447346. - typedef base::Callback<void( - const GURL& url, - int load_flags, - const net::ProxyConfig& data_reduction_proxy_config, - const net::ProxyRetryInfoMap& proxy_retry_info_map, - const DataReductionProxyParams* params, - net::ProxyInfo* result)> OnResolveProxyHandler; - // Provides an additional proxy configuration that can be consulted after // proxy resolution. Used to get the Data Reduction Proxy config and give it // to the OnResolveProxyHandler and RecordBytesHistograms. @@ -74,13 +61,9 @@ scoped_ptr<net::NetworkDelegate> network_delegate, DataReductionProxyParams* params, DataReductionProxyAuthRequestHandler* handler, - const ProxyConfigGetter& getter); + const DataReductionProxyConfigurator* configurator); ~DataReductionProxyNetworkDelegate() override; - // Initializes member variables used for overriding the proxy config. - // |proxy_config_getter_| must be non-NULL when this is called. - void InitProxyConfigOverrider(const OnResolveProxyHandler& proxy_handler); - // Initializes member variables to record data reduction proxy prefs and // report UMA. void InitStatisticsPrefsAndUMA( @@ -159,10 +142,7 @@ DataReductionProxyStatisticsPrefs* data_reduction_proxy_statistics_prefs_; - // TODO(sclittle): Factor this out, see http://crbug.com/447346. - OnResolveProxyHandler on_resolve_proxy_handler_; - - ProxyConfigGetter proxy_config_getter_; + const DataReductionProxyConfigurator* configurator_; DISALLOW_COPY_AND_ASSIGN(DataReductionProxyNetworkDelegate); };
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc index a385f89..50fc91a 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc
@@ -15,11 +15,15 @@ #include "base/test/histogram_tester.h" #include "base/time/time.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_auth_request_handler.h" +#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.h" +#include "components/data_reduction_proxy/core/common/data_reduction_proxy_event_store.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers_test_utils.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params_test_utils.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h" +#include "net/base/capturing_net_log.h" #include "net/base/host_port_pair.h" #include "net/base/load_flags.h" +#include "net/base/net_log.h" #include "net/http/http_response_headers.h" #include "net/proxy/proxy_config.h" #include "net/url_request/url_request.h" @@ -71,6 +75,7 @@ EXPECT_TRUE(test_job_factory_.SetProtocolHandler(url::kHttpScheme, test_job_interceptor_)); context_.set_job_factory(&test_job_factory_); + event_store_.reset(new DataReductionProxyEventStore(message_loop_proxy())); } const net::ProxyConfig& GetProxyConfig() const { @@ -115,6 +120,14 @@ return loop_.message_loop_proxy(); } + net::NetLog* net_log() { + return &net_log_; + } + + DataReductionProxyEventStore* event_store() { + return event_store_.get(); + } + private: base::MessageLoopForIO loop_; net::TestURLRequestContext context_; @@ -125,6 +138,8 @@ net::ProxyConfig config_; net::NetworkDelegate* network_delegate_; + net::CapturingNetLog net_log_; + scoped_ptr<DataReductionProxyEventStore> event_store_; }; TEST_F(DataReductionProxyNetworkDelegateTest, AuthenticationTest) { @@ -141,11 +156,15 @@ DataReductionProxyAuthRequestHandler auth_handler( kClient, params.get(), message_loop_proxy()); + scoped_ptr<DataReductionProxyConfigurator> configurator( + new DataReductionProxyConfigurator(message_loop_proxy(), net_log(), + event_store())); + scoped_ptr<DataReductionProxyNetworkDelegate> network_delegate( new DataReductionProxyNetworkDelegate( scoped_ptr<net::NetworkDelegate>(new TestNetworkDelegate()), params.get(), &auth_handler, - DataReductionProxyNetworkDelegate::ProxyConfigGetter())); + configurator.get())); set_network_delegate(network_delegate.get()); scoped_ptr<net::URLRequest> fake_request( @@ -202,13 +221,14 @@ kClient, params.get(), message_loop_proxy()); base::HistogramTester histogram_tester; + scoped_ptr<DataReductionProxyConfigurator> configurator( + new DataReductionProxyConfigurator(message_loop_proxy(), net_log(), + event_store())); scoped_ptr<DataReductionProxyNetworkDelegate> network_delegate( new DataReductionProxyNetworkDelegate( scoped_ptr<net::NetworkDelegate>( new TestNetworkDelegate()), params.get(), &auth_handler, - base::Bind( - &DataReductionProxyNetworkDelegateTest::GetProxyConfig, - base::Unretained(this)))); + configurator.get())); set_network_delegate(network_delegate.get());
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_statistics_prefs.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_statistics_prefs.h index 04e1947..a7e48a6 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_statistics_prefs.h +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_statistics_prefs.h
@@ -30,6 +30,7 @@ // |delay| amount of time. If |delay| is zero, the delayed pref service writes // directly to the PrefService and does not store the prefs in memory. All // prefs must be stored and read on the UI thread. +// TODO(bengr): Rename as DataReductionProxyCompressionStats. class DataReductionProxyStatisticsPrefs { public: // Constructs a data reduction proxy delayed pref service object using
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_usage_stats.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_usage_stats.cc index d32c618..7c1293b 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_usage_stats.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_usage_stats.cc
@@ -6,10 +6,11 @@ #include "base/bind.h" #include "base/callback.h" -#include "base/message_loop/message_loop_proxy.h" #include "base/metrics/histogram.h" #include "base/metrics/sparse_histogram.h" #include "base/prefs/pref_member.h" +#include "base/single_thread_task_runner.h" +#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_tamper_detection.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h" @@ -103,16 +104,18 @@ DataReductionProxyUsageStats::DataReductionProxyUsageStats( DataReductionProxyParams* params, - const scoped_refptr<MessageLoopProxy>& ui_thread_proxy) + DataReductionProxySettings* settings, + const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner) : data_reduction_proxy_params_(params), + settings_(settings), last_bypass_type_(BYPASS_EVENT_TYPE_MAX), triggering_request_(true), - ui_thread_proxy_(ui_thread_proxy), + ui_task_runner_(ui_task_runner), successful_requests_through_proxy_count_(0), proxy_net_errors_count_(0), unavailable_(false) { DCHECK(params); - + DCHECK(settings); NetworkChangeNotifier::AddNetworkChangeObserver(this); }; @@ -156,39 +159,6 @@ } } -void DataReductionProxyUsageStats::OnNetworkChanged( - NetworkChangeNotifier::ConnectionType type) { - DCHECK(thread_checker_.CalledOnValidThread()); - ClearRequestCounts(); -} - -void DataReductionProxyUsageStats::ClearRequestCounts() { - DCHECK(thread_checker_.CalledOnValidThread()); - successful_requests_through_proxy_count_ = 0; - proxy_net_errors_count_ = 0; -} - -void DataReductionProxyUsageStats::NotifyUnavailabilityIfChanged() { - bool prev_unavailable = unavailable_; - unavailable_ = - (proxy_net_errors_count_ >= kMinFailedRequestsWhenUnavailable && - successful_requests_through_proxy_count_ <= - kMaxSuccessfulRequestsWhenUnavailable); - if (prev_unavailable != unavailable_) { - ui_thread_proxy_->PostTask(FROM_HERE, base::Bind( - &DataReductionProxyUsageStats::NotifyUnavailabilityOnUIThread, - base::Unretained(this), - unavailable_)); - } -} - -void DataReductionProxyUsageStats::NotifyUnavailabilityOnUIThread( - bool unavailable) { - DCHECK(ui_thread_proxy_->BelongsToCurrentThread()); - if (!unavailable_callback_.is_null()) - unavailable_callback_.Run(unavailable); -} - void DataReductionProxyUsageStats::SetBypassType( DataReductionProxyBypassType type) { last_bypass_type_ = type; @@ -209,6 +179,53 @@ RecordMissingViaHeaderBytes(request); } +void DataReductionProxyUsageStats::OnProxyFallback( + const net::ProxyServer& bypassed_proxy, + int net_error) { + DataReductionProxyTypeInfo data_reduction_proxy_info; + if (bypassed_proxy.is_valid() && !bypassed_proxy.is_direct() && + data_reduction_proxy_params_->IsDataReductionProxy( + bypassed_proxy.host_port_pair(), &data_reduction_proxy_info)) { + if (data_reduction_proxy_info.is_ssl) + return; + + proxy_net_errors_count_++; + + // To account for the case when the proxy is reachable for sometime, and + // then gets blocked, we reset counts when number of errors exceed + // the threshold. + if (proxy_net_errors_count_ >= kMaxFailedRequestsBeforeReset && + successful_requests_through_proxy_count_ > + kMaxSuccessfulRequestsWhenUnavailable) { + ClearRequestCounts(); + } else { + NotifyUnavailabilityIfChanged(); + } + + if (!data_reduction_proxy_info.is_fallback) { + RecordDataReductionProxyBypassInfo( + true, false, bypassed_proxy, BYPASS_EVENT_TYPE_NETWORK_ERROR); + RecordDataReductionProxyBypassOnNetworkError( + true, bypassed_proxy, net_error); + } else { + RecordDataReductionProxyBypassInfo( + false, false, bypassed_proxy, BYPASS_EVENT_TYPE_NETWORK_ERROR); + RecordDataReductionProxyBypassOnNetworkError( + false, bypassed_proxy, net_error); + } + } +} + +void DataReductionProxyUsageStats::OnConnectComplete( + const net::HostPortPair& proxy_server, + int net_error) { + if (data_reduction_proxy_params_->IsDataReductionProxy(proxy_server, NULL)) { + UMA_HISTOGRAM_SPARSE_SLOWLY( + "DataReductionProxy.HTTPConnectCompleted", + std::abs(net_error)); + } +} + void DataReductionProxyUsageStats::RecordBypassedBytesHistograms( const net::URLRequest& request, const BooleanPrefMember& data_reduction_proxy_enabled, @@ -309,53 +326,63 @@ } } -void DataReductionProxyUsageStats::OnProxyFallback( - const net::ProxyServer& bypassed_proxy, - int net_error) { - DataReductionProxyTypeInfo data_reduction_proxy_info; - if (bypassed_proxy.is_valid() && !bypassed_proxy.is_direct() && - data_reduction_proxy_params_->IsDataReductionProxy( - bypassed_proxy.host_port_pair(), &data_reduction_proxy_info)) { - if (data_reduction_proxy_info.is_ssl) - return; +void DataReductionProxyUsageStats::RecordMissingViaHeaderBytes( + const URLRequest& request) { + // Responses that were served from cache should have been filtered out + // already. + DCHECK(!request.was_cached()); - proxy_net_errors_count_++; + if (!data_reduction_proxy_params_->WasDataReductionProxyUsed(&request, + NULL) || + HasDataReductionProxyViaHeader(request.response_headers(), NULL)) { + // Only track requests that used the data reduction proxy and had responses + // that were missing the data reduction proxy via header. + return; + } - // To account for the case when the proxy is reachable for sometime, and - // then gets blocked, we reset counts when number of errors exceed - // the threshold. - if (proxy_net_errors_count_ >= kMaxFailedRequestsBeforeReset && - successful_requests_through_proxy_count_ > - kMaxSuccessfulRequestsWhenUnavailable) { - ClearRequestCounts(); - } else { - NotifyUnavailabilityIfChanged(); - } - - if (!data_reduction_proxy_info.is_fallback) { - RecordDataReductionProxyBypassInfo( - true, false, bypassed_proxy, BYPASS_EVENT_TYPE_NETWORK_ERROR); - RecordDataReductionProxyBypassOnNetworkError( - true, bypassed_proxy, net_error); - } else { - RecordDataReductionProxyBypassInfo( - false, false, bypassed_proxy, BYPASS_EVENT_TYPE_NETWORK_ERROR); - RecordDataReductionProxyBypassOnNetworkError( - false, bypassed_proxy, net_error); - } + if (request.GetResponseCode() >= net::HTTP_BAD_REQUEST && + request.GetResponseCode() < net::HTTP_INTERNAL_SERVER_ERROR) { + // Track 4xx responses that are missing via headers separately. + UMA_HISTOGRAM_COUNTS("DataReductionProxy.MissingViaHeader.Bytes.4xx", + request.received_response_content_length()); + } else { + UMA_HISTOGRAM_COUNTS("DataReductionProxy.MissingViaHeader.Bytes.Other", + request.received_response_content_length()); } } -void DataReductionProxyUsageStats::OnConnectComplete( - const net::HostPortPair& proxy_server, - int net_error) { - if (data_reduction_proxy_params_->IsDataReductionProxy(proxy_server, NULL)) { - UMA_HISTOGRAM_SPARSE_SLOWLY( - "DataReductionProxy.HTTPConnectCompleted", - std::abs(net_error)); +void DataReductionProxyUsageStats::OnNetworkChanged( + NetworkChangeNotifier::ConnectionType type) { + DCHECK(thread_checker_.CalledOnValidThread()); + ClearRequestCounts(); +} + +void DataReductionProxyUsageStats::ClearRequestCounts() { + DCHECK(thread_checker_.CalledOnValidThread()); + successful_requests_through_proxy_count_ = 0; + proxy_net_errors_count_ = 0; +} + +void DataReductionProxyUsageStats::NotifyUnavailabilityIfChanged() { + bool prev_unavailable = unavailable_; + unavailable_ = + (proxy_net_errors_count_ >= kMinFailedRequestsWhenUnavailable && + successful_requests_through_proxy_count_ <= + kMaxSuccessfulRequestsWhenUnavailable); + if (prev_unavailable != unavailable_) { + ui_task_runner_->PostTask(FROM_HERE, base::Bind( + &DataReductionProxyUsageStats::NotifyUnavailabilityOnUIThread, + base::Unretained(this), + unavailable_)); } } +void DataReductionProxyUsageStats::NotifyUnavailabilityOnUIThread( + bool unavailable) { + DCHECK(ui_task_runner_->BelongsToCurrentThread()); + settings_->SetUnreachable(unavailable); +} + void DataReductionProxyUsageStats::RecordBypassedBytes( DataReductionProxyBypassType bypass_type, DataReductionProxyUsageStats::BypassedBytesType bypassed_bytes_type, @@ -471,31 +498,6 @@ } } -void DataReductionProxyUsageStats::RecordMissingViaHeaderBytes( - const URLRequest& request) { - // Responses that were served from cache should have been filtered out - // already. - DCHECK(!request.was_cached()); - - if (!data_reduction_proxy_params_->WasDataReductionProxyUsed(&request, - NULL) || - HasDataReductionProxyViaHeader(request.response_headers(), NULL)) { - // Only track requests that used the data reduction proxy and had responses - // that were missing the data reduction proxy via header. - return; - } - - if (request.GetResponseCode() >= net::HTTP_BAD_REQUEST && - request.GetResponseCode() < net::HTTP_INTERNAL_SERVER_ERROR) { - // Track 4xx responses that are missing via headers separately. - UMA_HISTOGRAM_COUNTS("DataReductionProxy.MissingViaHeader.Bytes.4xx", - request.received_response_content_length()); - } else { - UMA_HISTOGRAM_COUNTS("DataReductionProxy.MissingViaHeader.Bytes.Other", - request.received_response_content_length()); - } -} - } // namespace data_reduction_proxy
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_usage_stats.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_usage_stats.h index 33502e9..5e159e7e 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_usage_stats.h +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_usage_stats.h
@@ -6,8 +6,8 @@ #define COMPONENTS_DATA_REDUCTION_PROXY_CORE_BROWSER_DATA_REDUCTION_PROXY_USAGE_STATS_H_ #include "base/callback.h" -#include "base/message_loop/message_loop_proxy.h" #include "base/prefs/pref_member.h" +#include "base/single_thread_task_runner.h" #include "base/threading/thread_checker.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h" @@ -23,6 +23,9 @@ namespace data_reduction_proxy { +class DataReductionProxySettings; + +// TODO(bengr): Rename as DataReductionProxyBypassStats. class DataReductionProxyUsageStats : public net::NetworkChangeNotifier::NetworkChangeObserver { public: @@ -42,22 +45,19 @@ bool is_primary, const net::HttpResponseHeaders* headers); - // MessageLoopProxy instance is owned by io_thread. |params| outlives - // this class instance. + // |params| outlives this class instance. |settings| provides a hook to inform + // the user that the Data Reduction Proxy is unreachable, which occurs on the + // UI thread, hence the |ui_task_runner|. |settings| and |params| must not be + // null. DataReductionProxyUsageStats( DataReductionProxyParams* params, - const scoped_refptr<base::MessageLoopProxy>& ui_thread_proxy); + DataReductionProxySettings* settings, + const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner); + ~DataReductionProxyUsageStats() override; - // Sets the callback to be called on the UI thread when the unavailability - // status has changed. - void set_unavailable_callback( - const base::Callback<void(bool)>& unavailable_callback) { - unavailable_callback_ = unavailable_callback; - } - - // Callback intended to be called from |ChromeNetworkDelegate| when a - // request completes. This method is used to gather usage stats. + // Callback intended to be called from |DataReductionProxyNetworkDelegate| + // when a request completes. This method is used to gather usage stats. void OnUrlRequestCompleted(const net::URLRequest* request, bool started); // Records the last bypass reason to |bypass_type_| and sets @@ -119,10 +119,6 @@ void OnNetworkChanged( net::NetworkChangeNotifier::ConnectionType type) override; - // Called when request counts change. Resets counts if they exceed thresholds, - // and calls MaybeNotifyUnavailability otherwise. - void OnRequestCountChanged(); - // Clears request counts unconditionally. void ClearRequestCounts(); @@ -134,13 +130,21 @@ void NotifyUnavailabilityIfChanged(); void NotifyUnavailabilityOnUIThread(bool unavailable); + void RecordBypassedBytes( + DataReductionProxyBypassType bypass_type, + BypassedBytesType bypassed_bytes_type, + int64 content_length); + DataReductionProxyParams* data_reduction_proxy_params_; + + DataReductionProxySettings* settings_; + // The last reason for bypass as determined by // MaybeBypassProxyAndPrepareToRetry DataReductionProxyBypassType last_bypass_type_; // True if the last request triggered the current bypass. bool triggering_request_; - const scoped_refptr<base::MessageLoopProxy> ui_thread_proxy_; + const scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_; // The following 2 fields are used to determine if data reduction proxy is // unreachable. We keep a count of requests which should go through @@ -160,14 +164,6 @@ base::ThreadChecker thread_checker_; - void RecordBypassedBytes( - DataReductionProxyBypassType bypass_type, - BypassedBytesType bypassed_bytes_type, - int64 content_length); - - // Called when the unavailability status has changed. Runs on the UI thread. - base::Callback<void(bool)> unavailable_callback_; - DISALLOW_COPY_AND_ASSIGN(DataReductionProxyUsageStats); };
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_usage_stats_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_usage_stats_unittest.cc index e3cdd49d..3600421 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_usage_stats_unittest.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_usage_stats_unittest.cc
@@ -10,6 +10,7 @@ #include "base/memory/scoped_ptr.h" #include "base/metrics/histogram.h" #include "base/test/histogram_tester.h" +#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers_test_utils.h" #include "net/base/host_port_pair.h" #include "net/base/load_flags.h" @@ -57,8 +58,7 @@ public: DataReductionProxyUsageStatsTest() : loop_proxy_(base::MessageLoopProxy::current().get()), - context_(true), - unavailable_(false) { + context_(true) { context_.Init(); // The |test_job_factory_| takes ownership of the interceptor. @@ -70,10 +70,8 @@ mock_url_request_ = context_.CreateRequest(GURL(), net::IDLE, &delegate_, NULL); - } - - void NotifyUnavailable(bool unavailable) { - unavailable_ = unavailable; + settings_.reset(new DataReductionProxySettings( + new DataReductionProxyParamsMock())); } scoped_ptr<net::URLRequest> CreateURLRequestWithResponseHeaders( @@ -98,6 +96,10 @@ return fake_request.Pass(); } + bool IsUnreachable() const { + return settings_->IsDataReductionProxyUnreachable(); + } + // Required for base::MessageLoopProxy::current(). base::MessageLoopForUI loop_; base::MessageLoopProxy* loop_proxy_; @@ -110,7 +112,7 @@ // |test_job_interceptor_| is owned by |test_job_factory_|. net::TestJobInterceptor* test_job_interceptor_; net::URLRequestJobFactoryImpl test_job_factory_; - bool unavailable_; + scoped_ptr<DataReductionProxySettings> settings_; }; TEST_F(DataReductionProxyUsageStatsTest, IsDataReductionProxyUnreachable) { @@ -155,18 +157,15 @@ .WillRepeatedly(testing::Return(test_case.was_proxy_used)); scoped_ptr<DataReductionProxyUsageStats> usage_stats( - new DataReductionProxyUsageStats( - &mock_params_, loop_proxy_)); - usage_stats->set_unavailable_callback( - base::Bind(&DataReductionProxyUsageStatsTest::NotifyUnavailable, - base::Unretained(this))); + new DataReductionProxyUsageStats(&mock_params_, settings_.get(), + loop_proxy_)); usage_stats->OnProxyFallback(fallback_proxy_server, net::ERR_PROXY_CONNECTION_FAILED); usage_stats->OnUrlRequestCompleted(mock_url_request_.get(), false); base::MessageLoop::current()->RunUntilIdle(); - EXPECT_EQ(test_case.is_unreachable, unavailable_); + EXPECT_EQ(test_case.is_unreachable, IsUnreachable()); } } @@ -174,12 +173,8 @@ net::ProxyServer fallback_proxy_server = net::ProxyServer::FromURI("foo.com", net::ProxyServer::SCHEME_HTTP); scoped_ptr<DataReductionProxyUsageStats> usage_stats( - new DataReductionProxyUsageStats( - &mock_params_, loop_proxy_)); - usage_stats->set_unavailable_callback( - base::Bind(&DataReductionProxyUsageStatsTest::NotifyUnavailable, - base::Unretained(this))); - + new DataReductionProxyUsageStats(&mock_params_, settings_.get(), + loop_proxy_)); EXPECT_CALL(mock_params_, IsDataReductionProxy(testing::_, testing::_)) .WillOnce(testing::Return(true)); EXPECT_CALL(mock_params_, @@ -190,23 +185,20 @@ usage_stats->OnProxyFallback(fallback_proxy_server, net::ERR_PROXY_CONNECTION_FAILED); base::MessageLoop::current()->RunUntilIdle(); - EXPECT_TRUE(unavailable_); + EXPECT_TRUE(IsUnreachable()); // proxy succeeds usage_stats->OnUrlRequestCompleted(mock_url_request_.get(), false); base::MessageLoop::current()->RunUntilIdle(); - EXPECT_FALSE(unavailable_); + EXPECT_FALSE(IsUnreachable()); } TEST_F(DataReductionProxyUsageStatsTest, ProxyReachableThenUnreachable) { net::ProxyServer fallback_proxy_server = net::ProxyServer::FromURI("foo.com", net::ProxyServer::SCHEME_HTTP); scoped_ptr<DataReductionProxyUsageStats> usage_stats( - new DataReductionProxyUsageStats( - &mock_params_, loop_proxy_)); - usage_stats->set_unavailable_callback( - base::Bind(&DataReductionProxyUsageStatsTest::NotifyUnavailable, - base::Unretained(this))); + new DataReductionProxyUsageStats(&mock_params_, settings_.get(), + loop_proxy_)); EXPECT_CALL(mock_params_, WasDataReductionProxyUsed(mock_url_request_.get(), testing::_)) .WillOnce(testing::Return(true)); @@ -216,19 +208,19 @@ // Proxy succeeds. usage_stats->OnUrlRequestCompleted(mock_url_request_.get(), false); base::MessageLoop::current()->RunUntilIdle(); - EXPECT_FALSE(unavailable_); + EXPECT_FALSE(IsUnreachable()); // Then proxy falls back indefinitely. usage_stats->OnProxyFallback(fallback_proxy_server, net::ERR_PROXY_CONNECTION_FAILED); usage_stats->OnProxyFallback(fallback_proxy_server, - net::ERR_PROXY_CONNECTION_FAILED); + net::ERR_PROXY_CONNECTION_FAILED); usage_stats->OnProxyFallback(fallback_proxy_server, - net::ERR_PROXY_CONNECTION_FAILED); + net::ERR_PROXY_CONNECTION_FAILED); usage_stats->OnProxyFallback(fallback_proxy_server, - net::ERR_PROXY_CONNECTION_FAILED); + net::ERR_PROXY_CONNECTION_FAILED); base::MessageLoop::current()->RunUntilIdle(); - EXPECT_TRUE(unavailable_); + EXPECT_TRUE(IsUnreachable()); } TEST_F(DataReductionProxyUsageStatsTest, @@ -410,7 +402,8 @@ for (size_t i = 0; i < arraysize(test_cases); ++i) { base::HistogramTester histogram_tester; scoped_ptr<DataReductionProxyUsageStats> usage_stats( - new DataReductionProxyUsageStats(&mock_params_, loop_proxy_)); + new DataReductionProxyUsageStats(&mock_params_, settings_.get(), + loop_proxy_)); std::string raw_headers(test_cases[i].headers); HeadersToRaw(&raw_headers); @@ -475,7 +468,8 @@ for (size_t i = 0; i < arraysize(test_cases); ++i) { base::HistogramTester histogram_tester; scoped_ptr<DataReductionProxyUsageStats> usage_stats( - new DataReductionProxyUsageStats(&mock_params_, loop_proxy_)); + new DataReductionProxyUsageStats(&mock_params_, settings_.get(), + loop_proxy_)); std::string raw_headers("HTTP/1.1 200 OK\n" "Via: 1.1 Chrome-Compression-Proxy\n");
diff --git a/components/enhanced_bookmarks.gypi b/components/enhanced_bookmarks.gypi index ee0a8d4..2048493 100644 --- a/components/enhanced_bookmarks.gypi +++ b/components/enhanced_bookmarks.gypi
@@ -15,6 +15,7 @@ '../base/base.gyp:base', '../google_apis/google_apis.gyp:google_apis', '../net/net.gyp:net', + '../skia/skia.gyp:skia', '../sql/sql.gyp:sql', '../ui/gfx/gfx.gyp:gfx', '../url/url.gyp:url_lib', @@ -37,6 +38,7 @@ 'enhanced_bookmarks/enhanced_bookmark_model_observer.h', 'enhanced_bookmarks/enhanced_bookmark_utils.cc', 'enhanced_bookmarks/enhanced_bookmark_utils.h', + 'enhanced_bookmarks/image_record.h', 'enhanced_bookmarks/image_store.cc', 'enhanced_bookmarks/image_store.h', 'enhanced_bookmarks/image_store_util.cc',
diff --git a/components/enhanced_bookmarks/BUILD.gn b/components/enhanced_bookmarks/BUILD.gn index 0da3276a..7ce7ed5 100644 --- a/components/enhanced_bookmarks/BUILD.gn +++ b/components/enhanced_bookmarks/BUILD.gn
@@ -18,6 +18,7 @@ "enhanced_bookmark_model_observer.h", "enhanced_bookmark_utils.cc", "enhanced_bookmark_utils.h", + "image_record.h", "image_store.cc", "image_store.h", "image_store_util.cc", @@ -37,6 +38,7 @@ "//base", "//components/bookmarks/browser", "//components/enhanced_bookmarks/proto", + "//skia", "//sql", "//ui/gfx", "//url",
diff --git a/components/enhanced_bookmarks/DEPS b/components/enhanced_bookmarks/DEPS index 2716044..fd5c958 100644 --- a/components/enhanced_bookmarks/DEPS +++ b/components/enhanced_bookmarks/DEPS
@@ -7,14 +7,6 @@ "+jni", "+net", "+sql", + "+third_party/skia", "+ui", ] - -specific_include_rules = { - "image_store_unittest\.cc": [ - "+third_party/skia" - ], - "test_image_store\.cc": [ - "+third_party/skia" - ], -}
diff --git a/components/enhanced_bookmarks/bookmark_image_service.cc b/components/enhanced_bookmarks/bookmark_image_service.cc index 0831e38d..c2c019e 100644 --- a/components/enhanced_bookmarks/bookmark_image_service.cc +++ b/components/enhanced_bookmarks/bookmark_image_service.cc
@@ -5,12 +5,14 @@ #include "components/enhanced_bookmarks/bookmark_image_service.h" #include "base/single_thread_task_runner.h" +#include "base/task_runner_util.h" #include "base/thread_task_runner_handle.h" #include "base/threading/sequenced_worker_pool.h" #include "components/bookmarks/browser/bookmark_model.h" #include "components/bookmarks/browser/bookmark_model_observer.h" #include "components/enhanced_bookmarks/enhanced_bookmark_model.h" #include "components/enhanced_bookmarks/enhanced_bookmark_utils.h" +#include "components/enhanced_bookmarks/image_store_util.h" #include "components/enhanced_bookmarks/persistent_image_store.h" using bookmarks::BookmarkModel; @@ -33,11 +35,9 @@ void RetrieveImageFromStoreRelay( ImageStore* store, const GURL& page_url, - enhanced_bookmarks::BookmarkImageService::Callback callback, + enhanced_bookmarks::BookmarkImageService::ImageCallback callback, scoped_refptr<base::SingleThreadTaskRunner> origin_loop) { - std::pair<gfx::Image, GURL> image_data = store->Get(page_url); - origin_loop->PostTask( - FROM_HERE, base::Bind(callback, image_data.first, image_data.second)); + origin_loop->PostTask(FROM_HERE, base::Bind(callback, store->Get(page_url))); } } // namespace @@ -99,14 +99,13 @@ } void BookmarkImageService::SalientImageForUrl(const GURL& page_url, - Callback callback) { + ImageCallback callback) { DCHECK(CalledOnValidThread()); SalientImageForUrl(page_url, true, callback); } -void BookmarkImageService::RetrieveImageFromStore( - const GURL& page_url, - BookmarkImageService::Callback callback) { +void BookmarkImageService::RetrieveImageFromStore(const GURL& page_url, + ImageCallback callback) { DCHECK(CalledOnValidThread()); pool_->PostSequencedWorkerTaskWithShutdownBehavior( pool_->GetNamedSequenceToken(kSequenceToken), @@ -147,19 +146,18 @@ } void BookmarkImageService::FetchCallback(const GURL& page_url, - Callback original_callback, - const gfx::Image& image, - const GURL& image_url) { + ImageCallback original_callback, + const ImageRecord& record) { DCHECK(CalledOnValidThread()); - if (!image.IsEmpty() || !image_url.is_empty()) { - // Either the image was in the store or there is no image in the store, but - // an URL for an image is present, indicating that a previous attempt to - // download the image failed. Just return the image. - original_callback.Run(image, image_url); + if (!record.image.IsEmpty() || !record.url.is_empty()) { + // Either the record was in the store or there is no image in the store, but + // an URL for a record is present, indicating that a previous attempt to + // download the image failed. Just return the record. + original_callback.Run(record); } else { - // There is no image in the store, and no previous attempts to retrieve + // There is no record in the store, and no previous attempts to retrieve // one. Start a request to retrieve a salient image if there is an image - // url set on a bookmark, and then enqueue the request for the image to + // url set on a bookmark, and then enqueue the request for the record to // be triggered when the retrieval is finished. RetrieveSalientImageForPageUrl(page_url); SalientImageForUrl(page_url, false, original_callback); @@ -168,7 +166,7 @@ void BookmarkImageService::SalientImageForUrl(const GURL& page_url, bool fetch_from_bookmark, - Callback callback) { + ImageCallback callback) { DCHECK(CalledOnValidThread()); // If the request is done while the image is currently being retrieved, just @@ -194,9 +192,7 @@ const gfx::Image& image, const GURL& image_url) { DCHECK(CalledOnValidThread()); - StoreImage(image, image_url, page_url); - in_progress_page_urls_.erase(page_url); - ProcessRequests(page_url, image, image_url); + PostTaskToStoreImage(image, image_url, page_url); if (update_bookmarks && image_url.is_valid()) { const BookmarkNode* bookmark = enhanced_bookmark_model_->bookmark_model() @@ -215,20 +211,42 @@ return in_progress_page_urls_.find(page_url) != in_progress_page_urls_.end(); } -void BookmarkImageService::StoreImage(const gfx::Image& image, - const GURL& image_url, - const GURL& page_url) { - DCHECK(CalledOnValidThread()); +ImageRecord BookmarkImageService::StoreImage(const gfx::Image& image, + const GURL& image_url, + const GURL& page_url) { + ImageRecord image_info(image, image_url, SK_ColorBLACK); if (!image.IsEmpty()) { + image_info.dominant_color = DominantColorForImage(image); + // TODO(lpromero): this should be saved all the time, even when there is an + // empty image. http://crbug.com/451450 pool_->PostNamedSequencedWorkerTask( - kSequenceToken, - FROM_HERE, - base::Bind(&ImageStore::Insert, - base::Unretained(store_.get()), - page_url, - image_url, - image)); + kSequenceToken, FROM_HERE, + base::Bind(&ImageStore::Insert, base::Unretained(store_.get()), + page_url, image_info)); } + return image_info; +} + +void BookmarkImageService::PostTaskToStoreImage(const gfx::Image& image, + const GURL& image_url, + const GURL& page_url) { + DCHECK(CalledOnValidThread()); + + base::Callback<ImageRecord(void)> task = + base::Bind(&BookmarkImageService::StoreImage, base::Unretained(this), + image, image_url, page_url); + base::Callback<void(const ImageRecord&)> reply = + base::Bind(&BookmarkImageService::OnStoreImagePosted, + base::Unretained(this), page_url); + + base::PostTaskAndReplyWithResult(pool_.get(), FROM_HERE, task, reply); +} + +void BookmarkImageService::OnStoreImagePosted(const GURL& page_url, + const ImageRecord& image) { + DCHECK(CalledOnValidThread()); + in_progress_page_urls_.erase(page_url); + ProcessRequests(page_url, image); } void BookmarkImageService::RemoveImageForUrl(const GURL& page_url) { @@ -238,7 +256,7 @@ FROM_HERE, base::Bind(&ImageStore::Erase, base::Unretained(store_.get()), page_url)); in_progress_page_urls_.erase(page_url); - ProcessRequests(page_url, gfx::Image(), GURL()); + ProcessRequests(page_url, ImageRecord()); } void BookmarkImageService::ChangeImageURL(const GURL& from, const GURL& to) { @@ -250,7 +268,7 @@ from, to)); in_progress_page_urls_.erase(from); - ProcessRequests(from, gfx::Image(), GURL()); + ProcessRequests(from, ImageRecord()); } void BookmarkImageService::ClearAll() { @@ -261,11 +279,10 @@ FROM_HERE, base::Bind(&ImageStore::ClearAll, base::Unretained(store_.get()))); - for (std::map<const GURL, std::vector<Callback> >::const_iterator it = + for (std::map<const GURL, std::vector<ImageCallback>>::const_iterator it = callbacks_.begin(); - it != callbacks_.end(); - ++it) { - ProcessRequests(it->first, gfx::Image(), GURL()); + it != callbacks_.end(); ++it) { + ProcessRequests(it->first, ImageRecord()); } in_progress_page_urls_.erase(in_progress_page_urls_.begin(), @@ -273,15 +290,13 @@ } void BookmarkImageService::ProcessRequests(const GURL& page_url, - const gfx::Image& image, - const GURL& image_url) { + const ImageRecord& record) { DCHECK(CalledOnValidThread()); - std::vector<Callback> callbacks = callbacks_[page_url]; - for (std::vector<Callback>::const_iterator it = callbacks.begin(); - it != callbacks.end(); - ++it) { - it->Run(image, image_url); + std::vector<ImageCallback> callbacks = callbacks_[page_url]; + for (std::vector<ImageCallback>::const_iterator it = callbacks.begin(); + it != callbacks.end(); ++it) { + it->Run(record); } callbacks_.erase(page_url);
diff --git a/components/enhanced_bookmarks/bookmark_image_service.h b/components/enhanced_bookmarks/bookmark_image_service.h index 2ee8d61..5bf2637 100644 --- a/components/enhanced_bookmarks/bookmark_image_service.h +++ b/components/enhanced_bookmarks/bookmark_image_service.h
@@ -8,6 +8,7 @@ #include "base/memory/scoped_ptr.h" #include "base/memory/singleton.h" #include "components/bookmarks/browser/bookmark_model_observer.h" +#include "components/enhanced_bookmarks/image_record.h" #include "components/enhanced_bookmarks/image_store.h" #include "components/keyed_service/core/keyed_service.h" #include "net/url_request/url_request.h" @@ -36,7 +37,7 @@ ~BookmarkImageService() override; - typedef base::Callback<void(const gfx::Image&, const GURL& url)> Callback; + typedef base::Callback<void(const ImageRecord&)> ImageCallback; // KeyedService: void Shutdown() override; @@ -46,7 +47,7 @@ // a URL for this salient image available. The image (which may be empty) is // sent via the callback. The callback may be called synchronously if it is // possible. The callback is always triggered on the main thread. - void SalientImageForUrl(const GURL& page_url, Callback callback); + void SalientImageForUrl(const GURL& page_url, ImageCallback callback); // bookmarks::BookmarkModelObserver: void BookmarkNodeRemoved(bookmarks::BookmarkModel* model, @@ -108,28 +109,37 @@ EnhancedBookmarkModel* enhanced_bookmark_model_; private: - // Same as SalientImageForUrl(const GURL&, Callback) but can prevent the - // network request if fetch_from_bookmark is false. + // Same as SalientImageForUrl(const GURL&, ImageCallback) but can + // prevent the network request if fetch_from_bookmark is false. void SalientImageForUrl(const GURL& page_url, bool fetch_from_bookmark, - Callback stack_callback); + ImageCallback stack_callback); // Processes the requests that have been waiting on an image. - void ProcessRequests(const GURL& page_url, - const gfx::Image& image, - const GURL& image_url); + void ProcessRequests(const GURL& page_url, const ImageRecord& image); - // Once an image is retrieved this method updates the store with it. - void StoreImage(const gfx::Image& image, - const GURL& image_url, - const GURL& page_url); + // Once an image is retrieved this method updates the store with it. Returns + // the newly formed ImageRecord. This is typically called on |pool_|, the + // background sequenced worker pool for this object. + ImageRecord StoreImage(const gfx::Image& image, + const GURL& image_url, + const GURL& page_url); + + // Calls |StoreImage| in the background. This should only be called from the + // main thread. + void PostTaskToStoreImage(const gfx::Image& image, + const GURL& image_url, + const GURL& page_url); + + // Called when |StoreImage| as been posted. This should only be called from + // the main thread. + void OnStoreImagePosted(const GURL& page_url, const ImageRecord& image); // Called when retrieving an image from the image store fails, to trigger // retrieving the image from the url stored in the bookmark (if any). void FetchCallback(const GURL& page_url, - Callback original_callback, - const gfx::Image& image, - const GURL& image_url); + ImageCallback original_callback, + const ImageRecord& record); // Remove the image stored for this bookmark (if it exists). Called when a // bookmark is deleted. @@ -147,21 +157,20 @@ // main thread and the callback will be called on the main thread as well. The // callback will always be called. The returned image is nil if the image is // not present in the store. - void RetrieveImageFromStore(const GURL& page_url, - BookmarkImageService::Callback callback); + void RetrieveImageFromStore(const GURL& page_url, ImageCallback callback); // Maps a pageUrl to an image. scoped_ptr<ImageStore> store_; // All the callbacks waiting for a particular image. - std::map<const GURL, std::vector<Callback> > callbacks_; + std::map<const GURL, std::vector<ImageCallback>> callbacks_; // When a bookmark is changed, two messages are received on the // bookmarkModelObserver, one with the old state, one with the new. The url // before the change is saved in this instance variable. GURL previous_url_; - // The worker pool to enqueue the store requests onto. + // The worker pool to enqueue the requests onto. scoped_refptr<base::SequencedWorkerPool> pool_; DISALLOW_COPY_AND_ASSIGN(BookmarkImageService); };
diff --git a/components/enhanced_bookmarks/image_record.h b/components/enhanced_bookmarks/image_record.h new file mode 100644 index 0000000..dde3251 --- /dev/null +++ b/components/enhanced_bookmarks/image_record.h
@@ -0,0 +1,30 @@ +// Copyright 2015 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_ENHANCED_BOOKMARKS_IMAGE_RECORD_H_ +#define COMPONENTS_ENHANCED_BOOKMARKS_IMAGE_RECORD_H_ + +#include "third_party/skia/include/core/SkColor.h" +#include "ui/gfx/image/image.h" +#include "url/gurl.h" + +namespace enhanced_bookmarks { + +// Defines a record of a bookmark image in the ImageStore. +struct ImageRecord { + ImageRecord() : image(), url(), dominant_color(SK_ColorBLACK) {} + ImageRecord(const gfx::Image& image, const GURL& url, SkColor dominant_color) + : image(image), url(url), dominant_color(dominant_color) {} + + // The image data. + gfx::Image image; + // The URL that hosts the image. + GURL url; + // The dominant color of the image. + SkColor dominant_color; +}; + +} // namespace enhanced_bookmarks + +#endif // COMPONENTS_ENHANCED_BOOKMARKS_IMAGE_RECORD_H_
diff --git a/components/enhanced_bookmarks/image_store.cc b/components/enhanced_bookmarks/image_store.cc index a7e32e2..a3705781 100644 --- a/components/enhanced_bookmarks/image_store.cc +++ b/components/enhanced_bookmarks/image_store.cc
@@ -18,7 +18,7 @@ if (!HasKey(from)) return; - std::pair<gfx::Image, GURL> image_info = Get(from); + const enhanced_bookmarks::ImageRecord& record = Get(from); Erase(from); - Insert(to, image_info.second, image_info.first); + Insert(to, record); }
diff --git a/components/enhanced_bookmarks/image_store.h b/components/enhanced_bookmarks/image_store.h index 9d79506f..f4c63fa 100644 --- a/components/enhanced_bookmarks/image_store.h +++ b/components/enhanced_bookmarks/image_store.h
@@ -5,11 +5,11 @@ #ifndef COMPONENTS_ENHANCED_BOOKMARKS_IMAGE_STORE_H_ #define COMPONENTS_ENHANCED_BOOKMARKS_IMAGE_STORE_H_ -#include <map> #include <set> #include "base/sequence_checker.h" -#include "ui/gfx/image/image.h" +#include "components/enhanced_bookmarks/image_record.h" +#include "ui/gfx/geometry/size.h" class GURL; @@ -23,21 +23,22 @@ // Returns true if there is an image for this url. virtual bool HasKey(const GURL& page_url) = 0; - // Inserts an image and its url in the store for the the given page url. The - // image can be null indicating that the download of the image at this URL or - // encoding for insertion failed previously. On non-ios platforms, |image| + // Inserts an ImageRecord in the store for the given page url. The image can + // be null indicating that the download of the image at this URL or + // encoding for insertion failed previously. On non-iOS platforms, |image| // must have exactly one representation with a scale factor of 1. virtual void Insert(const GURL& page_url, - const GURL& image_url, - const gfx::Image& image) = 0; + const enhanced_bookmarks::ImageRecord& image_record) = 0; // Removes an image from the store. virtual void Erase(const GURL& page_url) = 0; - // Returns the image associated with this url. Returns empty image and url if - // there are no image for this url. It also returns the image_url where the - // image was downloaded from or failed to be downloaded from. - virtual std::pair<gfx::Image, GURL> Get(const GURL& page_url) = 0; + // Returns the image associated with this url. Returns an ImageRecord with an + // empty image if there is no image for this url. It also returns the + // image_url where the image was downloaded from or failed to be downloaded + // from. When the image is not empty, the dominant color of the image is also + // filled. + virtual enhanced_bookmarks::ImageRecord Get(const GURL& page_url) = 0; // Returns the size of the image stored for this URL or empty size if no // images are present.
diff --git a/components/enhanced_bookmarks/image_store_ios_unittest.mm b/components/enhanced_bookmarks/image_store_ios_unittest.mm index 78c57cb9..19dd5fa 100644 --- a/components/enhanced_bookmarks/image_store_ios_unittest.mm +++ b/components/enhanced_bookmarks/image_store_ios_unittest.mm
@@ -8,6 +8,7 @@ #include "base/files/scoped_temp_dir.h" #include "base/mac/scoped_cftyperef.h" +#include "components/enhanced_bookmarks/image_record.h" #include "components/enhanced_bookmarks/image_store_util.h" #include "components/enhanced_bookmarks/persistent_image_store.h" #include "components/enhanced_bookmarks/test_image_store.h" @@ -21,7 +22,7 @@ // Generates a gfx::Image with a random UIImage representation. Uses off-center // circle gradient to make all pixels slightly different in order to detect // small image alterations. -gfx::Image GenerateRandomUIImage(gfx::Size& size, float scale) { +gfx::Image GenerateRandomUIImage(const gfx::Size& size, float scale) { UIGraphicsBeginImageContextWithOptions(CGSizeMake(size.width(), size.height()), YES, // opaque. @@ -136,17 +137,19 @@ TYPED_TEST_CASE(ImageStoreUnitTestIOS, Implementations); TYPED_TEST(ImageStoreUnitTestIOS, StoringImagesPreservesScale) { - CGFloat scales[] = { 0.0, 1.0, 2.0 }; - gfx::Size image_size(42, 24); + const CGFloat scales[] = {0.0, 1.0, 2.0}; + const gfx::Size image_size(42, 24); for (unsigned long i = 0; i < arraysize(scales); i++) { - gfx::Image src_image(GenerateRandomUIImage(image_size, scales[i])); const GURL url("foo://bar"); - const GURL image_url("a.jpg"); - this->store_->Insert(url, image_url, src_image); - std::pair<gfx::Image, GURL> image_info = this->store_->Get(url); + const enhanced_bookmarks::ImageRecord image_in( + GenerateRandomUIImage(image_size, scales[i]), GURL("http://a.jpg"), + SK_ColorGREEN); + this->store_->Insert(url, image_in); + const enhanced_bookmarks::ImageRecord image_out = this->store_->Get(url); - EXPECT_EQ(image_url, image_info.second); - EXPECT_TRUE(CompareImages(src_image, image_info.first)); + EXPECT_EQ(image_in.url, image_out.url); + EXPECT_TRUE(CompareImages(image_in.image, image_out.image)); + EXPECT_EQ(image_in.dominant_color, image_out.dominant_color); } }
diff --git a/components/enhanced_bookmarks/image_store_unittest.cc b/components/enhanced_bookmarks/image_store_unittest.cc index 3724e085..e0d5ace 100644 --- a/components/enhanced_bookmarks/image_store_unittest.cc +++ b/components/enhanced_bookmarks/image_store_unittest.cc
@@ -4,13 +4,17 @@ #include "components/enhanced_bookmarks/image_store.h" +#include "base/files/file_path.h" #include "base/files/scoped_temp_dir.h" #include "base/strings/string_number_conversions.h" +#include "components/enhanced_bookmarks/image_record.h" #include "components/enhanced_bookmarks/image_store_util.h" #include "components/enhanced_bookmarks/persistent_image_store.h" #include "components/enhanced_bookmarks/test_image_store.h" +#include "sql/statement.h" #include "testing/platform_test.h" #include "third_party/skia/include/core/SkBitmap.h" +#include "third_party/skia/include/core/SkColor.h" #include "url/gurl.h" namespace { @@ -62,6 +66,45 @@ image_1_bytes->size()); } +bool CreateV1PersistentImageStoreDB(const base::FilePath& path) { + sql::Connection db; + if (!db.Open(path)) + return false; + + if (db.DoesTableExist("images_by_url")) + return false; + + const char kV1TableSql[] = + "CREATE TABLE IF NOT EXISTS images_by_url (" + "page_url LONGVARCHAR NOT NULL," + "image_url LONGVARCHAR NOT NULL," + "image_data BLOB," + "width INTEGER," + "height INTEGER" + ")"; + if (!db.Execute(kV1TableSql)) + return false; + + const char kV1IndexSql[] = + "CREATE INDEX IF NOT EXISTS images_by_url_idx ON images_by_url(page_url)"; + if (!db.Execute(kV1IndexSql)) + return false; + + sql::Statement statement(db.GetUniqueStatement( + "INSERT INTO images_by_url " + "(page_url, image_url, image_data, width, height) " + "VALUES (?, ?, ?, ?, ?)")); + statement.BindString(0, "foo://bar"); + statement.BindString(1, "http://a.jpg"); + scoped_refptr<base::RefCountedMemory> image_bytes = + enhanced_bookmarks::BytesForImage(GenerateWhiteImage()); + statement.BindBlob(2, image_bytes->front(), (int)image_bytes->size()); + statement.BindInt(3, 42); + statement.BindInt(4, 24); + + return statement.Run(); +} + // Factory functions for creating instances of the implementations. template <class T> ImageStore* CreateStore(base::ScopedTempDir& folder); @@ -127,7 +170,9 @@ } TYPED_TEST(ImageStoreUnitTest, StoreOne) { - this->store_->Insert(GURL("foo://bar"), GURL("a.jpg"), GenerateBlackImage()); + const enhanced_bookmarks::ImageRecord image( + GenerateBlackImage(), GURL("http://a.jpg"), SK_ColorBLACK); + this->store_->Insert(GURL("foo://bar"), image); std::set<GURL> all_urls; this->store_->GetAllPageUrls(&all_urls); @@ -137,25 +182,26 @@ } TYPED_TEST(ImageStoreUnitTest, Retrieve) { - gfx::Image src_image = GenerateBlackImage(42, 24); const GURL url("foo://bar"); - const GURL image_url("a.jpg"); - this->store_->Insert(url, image_url, src_image); + const enhanced_bookmarks::ImageRecord image_in( + CreateImage(42, 24, 1, 0, 0, 1), GURL("http://a.jpg"), SK_ColorBLUE); + this->store_->Insert(url, image_in); - std::pair<gfx::Image, GURL> image_info = this->store_->Get(url); - gfx::Size size = this->store_->GetSize(url); + const enhanced_bookmarks::ImageRecord image_out = this->store_->Get(url); + const gfx::Size size = this->store_->GetSize(url); - EXPECT_EQ(size.width(), 42); - EXPECT_EQ(size.height(), 24); - EXPECT_EQ(image_url, image_info.second); - EXPECT_TRUE(CompareImages(src_image, image_info.first)); + EXPECT_EQ(42, size.width()); + EXPECT_EQ(24, size.height()); + EXPECT_EQ(image_in.url, image_out.url); + EXPECT_TRUE(CompareImages(image_in.image, image_out.image)); + EXPECT_EQ(SK_ColorBLUE, image_out.dominant_color); } TYPED_TEST(ImageStoreUnitTest, Erase) { - gfx::Image src_image = GenerateBlackImage(); const GURL url("foo://bar"); - const GURL image_url("a.jpg"); - this->store_->Insert(url, image_url, src_image); + const enhanced_bookmarks::ImageRecord image( + GenerateBlackImage(), GURL("http://a.jpg"), SK_ColorBLACK); + this->store_->Insert(url, image); this->store_->Erase(url); EXPECT_FALSE(this->store_->HasKey(url)); @@ -166,9 +212,13 @@ TYPED_TEST(ImageStoreUnitTest, ClearAll) { const GURL url_foo("http://foo"); - this->store_->Insert(url_foo, GURL("foo.jpg"), GenerateBlackImage()); + const enhanced_bookmarks::ImageRecord black_image( + GenerateBlackImage(), GURL("http://a.jpg"), SK_ColorBLACK); + this->store_->Insert(url_foo, black_image); const GURL url_bar("http://bar"); - this->store_->Insert(url_foo, GURL("bar.jpg"), GenerateWhiteImage()); + const enhanced_bookmarks::ImageRecord white_image( + GenerateWhiteImage(), GURL("http://a.jpg"), SK_ColorWHITE); + this->store_->Insert(url_bar, white_image); this->store_->ClearAll(); @@ -180,54 +230,70 @@ } TYPED_TEST(ImageStoreUnitTest, Update) { - gfx::Image src_image1 = GenerateWhiteImage(); - gfx::Image src_image2 = GenerateBlackImage(); const GURL url("foo://bar"); - const GURL image_url1("1.jpg"); - this->store_->Insert(url, image_url1, src_image1); + const enhanced_bookmarks::ImageRecord image1(GenerateWhiteImage(), + GURL("1.jpg"), SK_ColorWHITE); + this->store_->Insert(url, image1); - const GURL image_url2("2.jpg"); - this->store_->Insert(url, image_url2, src_image2); + const enhanced_bookmarks::ImageRecord image2(GenerateBlackImage(), + GURL("2.jpg"), SK_ColorBLACK); + this->store_->Insert(url, image2); - std::pair<gfx::Image, GURL> image_info = this->store_->Get(url); + const enhanced_bookmarks::ImageRecord image_out = this->store_->Get(url); EXPECT_TRUE(this->store_->HasKey(url)); std::set<GURL> all_urls; this->store_->GetAllPageUrls(&all_urls); EXPECT_EQ(1u, all_urls.size()); - EXPECT_EQ(image_url2, image_info.second); - EXPECT_TRUE(CompareImages(src_image2, image_info.first)); + EXPECT_EQ(image2.url, image_out.url); + EXPECT_TRUE(CompareImages(image2.image, image_out.image)); + EXPECT_EQ(SK_ColorBLACK, image_out.dominant_color); } TYPED_TEST(ImageStoreUnitTest, Persistence) { - gfx::Image src_image = GenerateBlackImage(); const GURL url("foo://bar"); - const GURL image_url("a.jpg"); - this->store_->Insert(url, image_url, src_image); + const enhanced_bookmarks::ImageRecord image_in( + GenerateBlackImage(), GURL("http://a.jpg"), SK_ColorBLACK); + this->store_->Insert(url, image_in); this->ResetStore(); if (this->use_persistent_store()) { std::set<GURL> all_urls; this->store_->GetAllPageUrls(&all_urls); EXPECT_EQ(1u, all_urls.size()); - EXPECT_EQ(GURL("foo://bar"), *all_urls.begin()); - EXPECT_TRUE(this->store_->HasKey(GURL("foo://bar"))); - std::pair<gfx::Image, GURL> image_info = this->store_->Get(url); + EXPECT_EQ(url, *all_urls.begin()); + EXPECT_TRUE(this->store_->HasKey(url)); + const enhanced_bookmarks::ImageRecord image_out = this->store_->Get(url); - EXPECT_EQ(image_url, image_info.second); - EXPECT_TRUE(CompareImages(src_image, image_info.first)); + EXPECT_EQ(image_in.url, image_out.url); + EXPECT_TRUE(CompareImages(image_in.image, image_out.image)); + EXPECT_EQ(image_in.dominant_color, image_out.dominant_color); } else { std::set<GURL> all_urls; this->store_->GetAllPageUrls(&all_urls); EXPECT_EQ(0u, all_urls.size()); - EXPECT_FALSE(this->store_->HasKey(GURL("foo://bar"))); + EXPECT_FALSE(this->store_->HasKey(url)); } } +TYPED_TEST(ImageStoreUnitTest, MigrationToV2) { + // Migration is available only with persistent stores. + if (!this->use_persistent_store()) + return; + + // Set up v1 DB. + EXPECT_TRUE(CreateV1PersistentImageStoreDB(this->tempDir_.path().Append( + base::FilePath::FromUTF8Unsafe("BookmarkImageAndUrlStore.db")))); + + const enhanced_bookmarks::ImageRecord image_out = + this->store_->Get(GURL("foo://bar")); + EXPECT_EQ(SK_ColorWHITE, image_out.dominant_color); +} + TYPED_TEST(ImageStoreUnitTest, GetSize) { - gfx::Image src_image = GenerateBlackImage(); const GURL url("foo://bar"); - const GURL image_url("a.jpg"); + const enhanced_bookmarks::ImageRecord image_in( + GenerateBlackImage(), GURL("http://a.jpg"), SK_ColorBLACK); int64 size = 0; if (this->use_persistent_store()) { @@ -238,8 +304,8 @@ EXPECT_LE(this->store_->GetStoreSizeInBytes(), 1024); } for (int i = 0; i < 100; ++i) { - this->store_->Insert( - GURL(url.spec() + '/' + base::IntToString(i)), image_url, src_image); + this->store_->Insert(GURL(url.spec() + '/' + base::IntToString(i)), + image_in); EXPECT_GE(this->store_->GetStoreSizeInBytes(), size); size = this->store_->GetStoreSizeInBytes(); }
diff --git a/components/enhanced_bookmarks/image_store_util.cc b/components/enhanced_bookmarks/image_store_util.cc index 213b595..ef3979d9 100644 --- a/components/enhanced_bookmarks/image_store_util.cc +++ b/components/enhanced_bookmarks/image_store_util.cc
@@ -4,6 +4,8 @@ #include "components/enhanced_bookmarks/image_store_util.h" +#include "third_party/skia/include/core/SkBitmap.h" +#include "ui/gfx/color_analysis.h" #include "ui/gfx/image/image_skia.h" #include "ui/gfx/image/image_util.h" @@ -30,4 +32,8 @@ gfx::Image ImageForBytes(const scoped_refptr<base::RefCountedMemory>& bytes) { return gfx::ImageFrom1xJPEGEncodedData(bytes->front(), bytes->size()); } + +SkColor DominantColorForImage(const gfx::Image& image) { + return color_utils::CalculateKMeanColorOfBitmap(*image.ToSkBitmap()); +} }
diff --git a/components/enhanced_bookmarks/image_store_util.h b/components/enhanced_bookmarks/image_store_util.h index 0b9ecaf..8537197e 100644 --- a/components/enhanced_bookmarks/image_store_util.h +++ b/components/enhanced_bookmarks/image_store_util.h
@@ -6,6 +6,7 @@ #define COMPONENTS_ENHANCED_BOOKMARKS_IMAGE_STORE_UTIL_H_ #include "base/memory/ref_counted_memory.h" +#include "third_party/skia/include/core/SkColor.h" #include "ui/gfx/geometry/size.h" #include "ui/gfx/image/image.h" @@ -22,6 +23,9 @@ // returns a gfx::Image. If decoding fails, returns an empty image. gfx::Image ImageForBytes(const scoped_refptr<base::RefCountedMemory>& data); +// Returns the dominant color for |image|. This method can be slow on very large +// images. +SkColor DominantColorForImage(const gfx::Image& image); } #endif // COMPONENTS_ENHANCED_BOOKMARKS_IMAGE_STORE_UTIL_H_
diff --git a/components/enhanced_bookmarks/image_store_util_ios.mm b/components/enhanced_bookmarks/image_store_util_ios.mm index 5d027cb..98a08db 100644 --- a/components/enhanced_bookmarks/image_store_util_ios.mm +++ b/components/enhanced_bookmarks/image_store_util_ios.mm
@@ -8,6 +8,8 @@ #include "base/mac/scoped_cftyperef.h" #include "base/mac/scoped_nsobject.h" +#include "third_party/skia/include/core/SkBitmap.h" +#include "ui/gfx/color_analysis.h" namespace { // An implementation of RefCountedMemory, where the bytes are stored in a @@ -45,4 +47,8 @@ [NSData dataWithBytes:data->front() length:data->size()]] retain]); } +SkColor DominantColorForImage(const gfx::Image& image) { + return color_utils::CalculateKMeanColorOfBitmap(*image.ToSkBitmap()); +} + } // namespace enhanced_bookmarks
diff --git a/components/enhanced_bookmarks/persistent_image_store.cc b/components/enhanced_bookmarks/persistent_image_store.cc index 0108c85..1061b69 100644 --- a/components/enhanced_bookmarks/persistent_image_store.cc +++ b/components/enhanced_bookmarks/persistent_image_store.cc
@@ -5,6 +5,7 @@ #include "components/enhanced_bookmarks/persistent_image_store.h" #include "base/files/file.h" +#include "base/logging.h" #include "components/enhanced_bookmarks/image_store_util.h" #include "sql/statement.h" #include "sql/transaction.h" @@ -12,6 +13,11 @@ #include "url/gurl.h" namespace { +// Current version number. Databases are written at the "current" version +// number, but any previous version that can read the "compatible" one can make +// do with our database without *too* many bad effects. +const int kCurrentVersionNumber = 2; +const int kCompatibleVersionNumber = 1; bool InitTables(sql::Connection& db) { const char kTableSql[] = @@ -20,7 +26,8 @@ "image_url LONGVARCHAR NOT NULL," "image_data BLOB," "width INTEGER," - "height INTEGER" + "height INTEGER," + "image_dominant_color INTEGER" ")"; if (!db.Execute(kTableSql)) return false; @@ -35,7 +42,60 @@ return true; } +// V1 didn't store the dominant color of an image. Creates the column to store +// a dominant color in the database. The value will be filled when queried for a +// one time cost. +bool MigrateImagesWithNoDominantColor(sql::Connection& db) { + if (!db.DoesTableExist("images_by_url")) { + NOTREACHED() << "images_by_url table should exist before migration."; + return false; + } + + if (!db.DoesColumnExist("images_by_url", "image_dominant_color")) { + // The initial version doesn't have the image_dominant_color column, it is + // added to the table here. + if (!db.Execute( + "ALTER TABLE images_by_url " + "ADD COLUMN image_dominant_color INTEGER")) { + return false; + } + } + return true; +} + +sql::InitStatus EnsureCurrentVersion(sql::Connection& db, + sql::MetaTable& meta_table) { + // 1- Newer databases than designed for can't be read. + if (meta_table.GetCompatibleVersionNumber() > kCurrentVersionNumber) { + LOG(WARNING) << "Image DB is too new."; + return sql::INIT_TOO_NEW; + } + + int cur_version = meta_table.GetVersionNumber(); + + // 2- Put migration code here. + + if (cur_version == 1) { + if (!MigrateImagesWithNoDominantColor(db)) { + LOG(WARNING) << "Unable to update image DB to version 1."; + return sql::INIT_FAILURE; + } + ++cur_version; + meta_table.SetVersionNumber(cur_version); + meta_table.SetCompatibleVersionNumber( + std::min(cur_version, kCompatibleVersionNumber)); + } + + // 3- When the version is too old, just try to continue anyway, there should + // not be a released product that makes a database too old to handle. + LOG_IF(WARNING, cur_version < kCurrentVersionNumber) + << "Image DB version " << cur_version << " is too old to handle."; + + return sql::INIT_OK; +} + sql::InitStatus OpenDatabaseImpl(sql::Connection& db, + sql::MetaTable& meta_table, const base::FilePath& db_path) { DCHECK(!db.is_open()); @@ -44,22 +104,33 @@ // TODO(noyau): Set error callback? // Run the database in exclusive mode. Nobody else should be accessing the - // database while we're running, and this will give somewhat improved perf. + // database while running, and this will give somewhat improved performance. db.set_exclusive_locking(); if (!db.Open(db_path)) return sql::INIT_FAILURE; - // Scope initialization in a transaction so we can't be partially initialized. + // Scope initialization in a transaction so it can't be partially initialized. sql::Transaction transaction(&db); if (!transaction.Begin()) return sql::INIT_FAILURE; - // Create the tables. - if (!InitTables(db) || - !InitIndices(db)) { + // Initialize the meta table. + int cur_version = meta_table.DoesTableExist(&db) + ? kCurrentVersionNumber + : 1; // Only v1 didn't have a meta table. + if (!meta_table.Init(&db, cur_version, + std::min(cur_version, kCompatibleVersionNumber))) return sql::INIT_FAILURE; - } + + // Create the tables. + if (!InitTables(db) || !InitIndices(db)) + return sql::INIT_FAILURE; + + // Check the version. + sql::InitStatus version_status = EnsureCurrentVersion(db, meta_table); + if (version_status != sql::INIT_OK) + return version_status; // Initialization is complete. if (!transaction.Commit()) @@ -90,24 +161,25 @@ return !!count; } -void PersistentImageStore::Insert(const GURL& page_url, - const GURL& image_url, - const gfx::Image& image) { +void PersistentImageStore::Insert( + const GURL& page_url, + const enhanced_bookmarks::ImageRecord& record) { DCHECK(sequence_checker_.CalledOnValidSequencedThread()); if (OpenDatabase() != sql::INIT_OK) return; Erase(page_url); // Remove previous image for this url, if any. - sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE, + sql::Statement statement(db_.GetCachedStatement( + SQL_FROM_HERE, "INSERT INTO images_by_url " - "(page_url, image_url, image_data, width, height)" - "VALUES (?, ?, ?, ?, ?)")); + "(page_url, image_url, image_data, width, height, image_dominant_color)" + "VALUES (?, ?, ?, ?, ?, ?)")); statement.BindString(0, page_url.possibly_invalid_spec()); - statement.BindString(1, image_url.possibly_invalid_spec()); + statement.BindString(1, record.url.possibly_invalid_spec()); scoped_refptr<base::RefCountedMemory> image_bytes = - enhanced_bookmarks::BytesForImage(image); + enhanced_bookmarks::BytesForImage(record.image); // Insert an empty image in case encoding fails. if (!image_bytes.get()) @@ -117,8 +189,9 @@ statement.BindBlob(2, image_bytes->front(), (int)image_bytes->size()); - statement.BindInt(3, image.Size().width()); - statement.BindInt(4, image.Size().height()); + statement.BindInt(3, record.image.Size().width()); + statement.BindInt(4, record.image.Size().height()); + statement.BindInt(5, record.dominant_color); statement.Run(); } @@ -133,27 +206,59 @@ statement.Run(); } -std::pair<gfx::Image, GURL> PersistentImageStore::Get(const GURL& page_url) { +enhanced_bookmarks::ImageRecord PersistentImageStore::Get( + const GURL& page_url) { DCHECK(sequence_checker_.CalledOnValidSequencedThread()); + enhanced_bookmarks::ImageRecord image_record; if (OpenDatabase() != sql::INIT_OK) - return std::make_pair(gfx::Image(), GURL()); + return image_record; - sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE, - "SELECT image_data, image_url FROM images_by_url WHERE page_url = ?")); + bool stored_image_record_needs_update = false; - statement.BindString(0, page_url.possibly_invalid_spec()); + // Scope the SELECT statement. + { + sql::Statement statement(db_.GetCachedStatement( + SQL_FROM_HERE, + "SELECT image_data, image_url, image_dominant_color FROM images_by_url " + "WHERE page_url = ?")); - while (statement.Step()) { + statement.BindString(0, page_url.possibly_invalid_spec()); + + if (!statement.Step()) + return image_record; + + // Image. if (statement.ColumnByteLength(0) > 0) { scoped_refptr<base::RefCountedBytes> data(new base::RefCountedBytes()); statement.ColumnBlobAsVector(0, &data->data()); - - return std::make_pair(enhanced_bookmarks::ImageForBytes(data), - GURL(statement.ColumnString(1))); + image_record.image = enhanced_bookmarks::ImageForBytes(data); } + + // URL. + image_record.url = GURL(statement.ColumnString(1)); + + // Dominant color. + if (statement.ColumnType(2) != sql::COLUMN_TYPE_NULL) { + image_record.dominant_color = SkColor(statement.ColumnInt(2)); + } else { + // The dominant color was not computed when the image was first + // stored. + // Compute it now. + image_record.dominant_color = + enhanced_bookmarks::DominantColorForImage(image_record.image); + stored_image_record_needs_update = true; + } + + // Make sure there is only one record for page_url. + DCHECK(!statement.Step()); } - return std::make_pair(gfx::Image(), GURL()); + if (stored_image_record_needs_update) { + Erase(page_url); + Insert(page_url, image_record); + } + + return image_record; } gfx::Size PersistentImageStore::GetSize(const GURL& page_url) { @@ -217,7 +322,7 @@ sql::InitStatus status = sql::INIT_FAILURE; for (size_t i = 0; i < kAttempts; ++i) { - status = OpenDatabaseImpl(db_, path_); + status = OpenDatabaseImpl(db_, meta_table_, path_); if (status == sql::INIT_OK) return status;
diff --git a/components/enhanced_bookmarks/persistent_image_store.h b/components/enhanced_bookmarks/persistent_image_store.h index bc715a50..5a0c41d 100644 --- a/components/enhanced_bookmarks/persistent_image_store.h +++ b/components/enhanced_bookmarks/persistent_image_store.h
@@ -10,6 +10,7 @@ #include "base/files/file_path.h" #include "sql/connection.h" #include "sql/init_status.h" +#include "sql/meta_table.h" // The PersistentImageStore is an implementation of ImageStore that persists its // data on disk. @@ -19,10 +20,9 @@ explicit PersistentImageStore(const base::FilePath& path); bool HasKey(const GURL& page_url) override; void Insert(const GURL& page_url, - const GURL& image_url, - const gfx::Image& image) override; + const enhanced_bookmarks::ImageRecord& image) override; void Erase(const GURL& page_url) override; - std::pair<gfx::Image, GURL> Get(const GURL& page_url) override; + enhanced_bookmarks::ImageRecord Get(const GURL& page_url) override; gfx::Size GetSize(const GURL& page_url) override; void GetAllPageUrls(std::set<GURL>* urls) override; void ClearAll() override; @@ -36,6 +36,7 @@ const base::FilePath path_; sql::Connection db_; + sql::MetaTable meta_table_; DISALLOW_COPY_AND_ASSIGN(PersistentImageStore); };
diff --git a/components/enhanced_bookmarks/test_image_store.cc b/components/enhanced_bookmarks/test_image_store.cc index 19d505f..9b11cdf 100644 --- a/components/enhanced_bookmarks/test_image_store.cc +++ b/components/enhanced_bookmarks/test_image_store.cc
@@ -18,15 +18,11 @@ } void TestImageStore::Insert(const GURL& page_url, - const GURL& image_url, - const gfx::Image& image) { + const enhanced_bookmarks::ImageRecord& image) { DCHECK(sequence_checker_.CalledOnValidSequencedThread()); Erase(page_url); - store_.insert(std::make_pair( - page_url, - std::make_pair(image, - image_url))); + store_.insert(std::make_pair(page_url, image)); } void TestImageStore::Erase(const GURL& page_url) { @@ -35,14 +31,13 @@ store_.erase(page_url); } -std::pair<gfx::Image, GURL> TestImageStore::Get(const GURL& page_url) { +enhanced_bookmarks::ImageRecord TestImageStore::Get(const GURL& page_url) { DCHECK(sequence_checker_.CalledOnValidSequencedThread()); - ImageMap::const_iterator pair_enumerator = store_.find(page_url); - if (pair_enumerator == store_.end()) - return std::make_pair(gfx::Image(), GURL()); + if (store_.find(page_url) == store_.end()) + return enhanced_bookmarks::ImageRecord(); - return std::make_pair(store_[page_url].first, store_[page_url].second); + return store_[page_url]; } gfx::Size TestImageStore::GetSize(const GURL& page_url) { @@ -52,7 +47,7 @@ if (pair_enumerator == store_.end()) return gfx::Size(); - return store_[page_url].first.Size(); + return store_[page_url].image.Size(); } void TestImageStore::GetAllPageUrls(std::set<GURL>* urls) { @@ -77,9 +72,10 @@ size += sizeof(it->first); size += it->first.spec().length(); size += sizeof(it->second); - SkBitmap bitmap = it->second.first.AsBitmap(); + SkBitmap bitmap = it->second.image.AsBitmap(); size += bitmap.getSize(); - size += it->second.second.spec().length(); + size += it->second.url.spec().length(); + size += sizeof(it->second.dominant_color); } return size; }
diff --git a/components/enhanced_bookmarks/test_image_store.h b/components/enhanced_bookmarks/test_image_store.h index 5acef167c..460a285 100644 --- a/components/enhanced_bookmarks/test_image_store.h +++ b/components/enhanced_bookmarks/test_image_store.h
@@ -15,10 +15,9 @@ TestImageStore(); bool HasKey(const GURL& page_url) override; void Insert(const GURL& page_url, - const GURL& image_url, - const gfx::Image& image) override; + const enhanced_bookmarks::ImageRecord& image) override; void Erase(const GURL& page_url) override; - std::pair<gfx::Image, GURL> Get(const GURL& page_url) override; + enhanced_bookmarks::ImageRecord Get(const GURL& page_url) override; gfx::Size GetSize(const GURL& page_url) override; void GetAllPageUrls(std::set<GURL>* urls) override; void ClearAll() override; @@ -28,7 +27,7 @@ ~TestImageStore() override; private: - typedef std::map<const GURL, std::pair<gfx::Image, const GURL> > ImageMap; + typedef std::map<const GURL, enhanced_bookmarks::ImageRecord> ImageMap; ImageMap store_; DISALLOW_COPY_AND_ASSIGN(TestImageStore);
diff --git a/components/history.gypi b/components/history.gypi index e1b2516..11976bc 100644 --- a/components/history.gypi +++ b/components/history.gypi
@@ -33,6 +33,8 @@ 'history/core/browser/download_row.h', 'history/core/browser/download_types.cc', 'history/core/browser/download_types.h', + 'history/core/browser/expire_history_backend.cc', + 'history/core/browser/expire_history_backend.h', 'history/core/browser/history_backend_notifier.h', 'history/core/browser/history_backend_observer.h', 'history/core/browser/history_client.cc',
diff --git a/components/history/core/browser/BUILD.gn b/components/history/core/browser/BUILD.gn index a84de5bb..b524e860 100644 --- a/components/history/core/browser/BUILD.gn +++ b/components/history/core/browser/BUILD.gn
@@ -13,6 +13,8 @@ "download_row.h", "download_types.cc", "download_types.h", + "expire_history_backend.cc", + "expire_history_backend.h", "history_backend_notifier.h", "history_backend_observer.h", "history_client.cc",
diff --git a/chrome/browser/history/expire_history_backend.cc b/components/history/core/browser/expire_history_backend.cc similarity index 99% rename from chrome/browser/history/expire_history_backend.cc rename to components/history/core/browser/expire_history_backend.cc index 1e33dd1..e115f84e 100644 --- a/chrome/browser/history/expire_history_backend.cc +++ b/components/history/core/browser/expire_history_backend.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 "chrome/browser/history/expire_history_backend.h" +#include "components/history/core/browser/expire_history_backend.h" #include <algorithm> #include <functional>
diff --git a/chrome/browser/history/expire_history_backend.h b/components/history/core/browser/expire_history_backend.h similarity index 97% rename from chrome/browser/history/expire_history_backend.h rename to components/history/core/browser/expire_history_backend.h index 7975966..ac70314 100644 --- a/chrome/browser/history/expire_history_backend.h +++ b/components/history/core/browser/expire_history_backend.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 CHROME_BROWSER_HISTORY_EXPIRE_HISTORY_BACKEND_H_ -#define CHROME_BROWSER_HISTORY_EXPIRE_HISTORY_BACKEND_H_ +#ifndef COMPONENTS_HISTORY_CORE_BROWSER_EXPIRE_HISTORY_BACKEND_H_ +#define COMPONENTS_HISTORY_CORE_BROWSER_EXPIRE_HISTORY_BACKEND_H_ #include <queue> #include <set> @@ -268,4 +268,4 @@ } // namespace history -#endif // CHROME_BROWSER_HISTORY_EXPIRE_HISTORY_BACKEND_H_ +#endif // COMPONENTS_HISTORY_CORE_BROWSER_EXPIRE_HISTORY_BACKEND_H_
diff --git a/components/history/core/browser/history_service_observer.h b/components/history/core/browser/history_service_observer.h index 9ea82e27..834f39b 100644 --- a/components/history/core/browser/history_service_observer.h +++ b/components/history/core/browser/history_service_observer.h
@@ -58,6 +58,11 @@ KeywordID keyword_id, const base::string16& term) {} + // Sent when a keyword search term is deleted. + // |url_id| is the id of the url row. + virtual void OnKeywordSearchTermDeleted(HistoryService* history_service, + URLID url_id) {} + private: DISALLOW_COPY_AND_ASSIGN(HistoryServiceObserver); };
diff --git a/components/invalidation/android/java/src/org/chromium/components/invalidation/InvalidationClientService.java b/components/invalidation/android/java/src/org/chromium/components/invalidation/InvalidationClientService.java index 22688f52..0c85e4a 100644 --- a/components/invalidation/android/java/src/org/chromium/components/invalidation/InvalidationClientService.java +++ b/components/invalidation/android/java/src/org/chromium/components/invalidation/InvalidationClientService.java
@@ -21,12 +21,13 @@ import org.chromium.base.ApplicationStatus; import org.chromium.base.CollectionUtil; import org.chromium.base.VisibleForTesting; +import org.chromium.sync.AndroidSyncSettings; +import org.chromium.sync.SyncConstants; import org.chromium.sync.internal_api.pub.base.ModelType; import org.chromium.sync.notifier.InvalidationClientNameProvider; import org.chromium.sync.notifier.InvalidationIntentProtocol; import org.chromium.sync.notifier.InvalidationPreferences; import org.chromium.sync.notifier.InvalidationPreferences.EditContext; -import org.chromium.sync.notifier.SyncStatusHelper; import org.chromium.sync.signin.AccountManagerHelper; import org.chromium.sync.signin.ChromeSigninController; @@ -82,8 +83,8 @@ // match the stored account. Then, if a client should be running, ensureClientStartState // will start a new one if needed. I.e., these two functions work together to restart the // client when the account changes. - Account account = intent.hasExtra(InvalidationIntentProtocol.EXTRA_ACCOUNT) ? - (Account) intent.getParcelableExtra(InvalidationIntentProtocol.EXTRA_ACCOUNT) + Account account = intent.hasExtra(InvalidationIntentProtocol.EXTRA_ACCOUNT) + ? (Account) intent.getParcelableExtra(InvalidationIntentProtocol.EXTRA_ACCOUNT) : null; ensureAccount(account); @@ -350,10 +351,10 @@ // read the current registrations from preferences before we write the new values, so that // we can take the diff of the two registration sets and determine which registration change // calls to make. - Set<ObjectId> existingSyncRegistrations = (sClientId == null) ? - null : readSyncRegistrationsFromPrefs(); - Set<ObjectId> existingNonSyncRegistrations = (sClientId == null) ? - null : readNonSyncRegistrationsFromPrefs(); + Set<ObjectId> existingSyncRegistrations = (sClientId == null) + ? null : readSyncRegistrationsFromPrefs(); + Set<ObjectId> existingNonSyncRegistrations = (sClientId == null) + ? null : readNonSyncRegistrationsFromPrefs(); // Write the new sync types/object ids to preferences. We do not expand the syncTypes to // take into account the ALL_TYPES_TYPE at this point; we want to persist the wildcard @@ -381,10 +382,10 @@ // wildcard. // When computing the desired set of object ids, if only sync types were provided, then // keep the existing non-sync types, and vice-versa. - Set<ObjectId> desiredSyncRegistrations = syncTypes != null ? - ModelType.syncTypesToObjectIds(syncTypes) : existingSyncRegistrations; - Set<ObjectId> desiredNonSyncRegistrations = objectIds != null ? - objectIds : existingNonSyncRegistrations; + Set<ObjectId> desiredSyncRegistrations = syncTypes != null + ? ModelType.syncTypesToObjectIds(syncTypes) : existingSyncRegistrations; + Set<ObjectId> desiredNonSyncRegistrations = objectIds != null + ? objectIds : existingNonSyncRegistrations; Set<ObjectId> desiredRegistrations = joinRegistrations(desiredNonSyncRegistrations, desiredSyncRegistrations); Set<ObjectId> existingRegistrations = joinRegistrations(existingNonSyncRegistrations, @@ -443,7 +444,7 @@ bundle.putString("payload", (payload == null) ? "" : payload); } Account account = ChromeSigninController.get(this).getSignedInUser(); - String contractAuthority = SyncStatusHelper.get(this).getContractAuthority(); + String contractAuthority = AndroidSyncSettings.get(this).getContractAuthority(); requestSyncFromContentResolver(bundle, account, contractAuthority); } @@ -471,7 +472,7 @@ /** Returns whether sync is enabled. LLocal method so it can be overridden in tests. */ @VisibleForTesting boolean isSyncEnabled() { - return SyncStatusHelper.get(getApplicationContext()).isSyncEnabled(); + return AndroidSyncSettings.get(getApplicationContext()).isSyncEnabled(); } /** @@ -495,7 +496,7 @@ } private static String getOAuth2ScopeWithType() { - return "oauth2:" + SyncStatusHelper.CHROME_SYNC_OAUTH2_SCOPE; + return "oauth2:" + SyncConstants.CHROME_SYNC_OAUTH2_SCOPE; } private static void setClientId(byte[] clientId) {
diff --git a/components/metrics/BUILD.gn b/components/metrics/BUILD.gn index 964bf94..b181fdc 100644 --- a/components/metrics/BUILD.gn +++ b/components/metrics/BUILD.gn
@@ -64,6 +64,10 @@ if (is_chromeos) { deps += [ ":serialization" ] } + + if (is_win) { + sources -= [ "machine_id_provider_stub.cc" ] + } } # GYP version: components/metrics.gypi:metrics_gpu
diff --git a/components/metrics/net/wifi_access_point_info_provider_chromeos.cc b/components/metrics/net/wifi_access_point_info_provider_chromeos.cc index 314ddc5..cb0adf1 100644 --- a/components/metrics/net/wifi_access_point_info_provider_chromeos.cc +++ b/components/metrics/net/wifi_access_point_info_provider_chromeos.cc
@@ -62,8 +62,8 @@ const std::string &service_path, const base::DictionaryValue& properties) { // Skip services that contain "_nomap" in the SSID. - std::string ssid = - chromeos::shill_property_util::GetSSIDFromProperties(properties, NULL); + std::string ssid = chromeos::shill_property_util::GetSSIDFromProperties( + properties, false /* verbose_logging */, nullptr); if (ssid.find("_nomap", 0) != std::string::npos) return;
diff --git a/components/metrics/net/wifi_access_point_info_provider_chromeos.h b/components/metrics/net/wifi_access_point_info_provider_chromeos.h index c6980ec..fc6fbab 100644 --- a/components/metrics/net/wifi_access_point_info_provider_chromeos.h +++ b/components/metrics/net/wifi_access_point_info_provider_chromeos.h
@@ -23,7 +23,7 @@ public base::SupportsWeakPtr<WifiAccessPointInfoProviderChromeos> { public: WifiAccessPointInfoProviderChromeos(); - virtual ~WifiAccessPointInfoProviderChromeos(); + ~WifiAccessPointInfoProviderChromeos() override; // WifiAccessPointInfoProvider: bool GetInfo(WifiAccessPointInfo* info) override;
diff --git a/components/metrics/proto/cast_logs.proto b/components/metrics/proto/cast_logs.proto index 327a4eb..2cf56aa 100644 --- a/components/metrics/proto/cast_logs.proto +++ b/components/metrics/proto/cast_logs.proto
@@ -20,6 +20,7 @@ enum CastProductType { CAST_PRODUCT_TYPE_UNKNOWN = 0; CAST_PRODUCT_TYPE_CHROMECAST = 1; + CAST_PRODUCT_TYPE_AUDIO = 3; CAST_PRODUCT_TYPE_ANDROID_TV = 4; } optional CastProductType type = 1;
diff --git a/components/nacl/broker/nacl_broker_listener.cc b/components/nacl/broker/nacl_broker_listener.cc index 6554f0ba..6dec3e6 100644 --- a/components/nacl/broker/nacl_broker_listener.cc +++ b/components/nacl/broker/nacl_broker_listener.cc
@@ -127,7 +127,7 @@ int32 pid, base::ProcessHandle process_handle, const std::string& startup_info) { NaClStartDebugExceptionHandlerThread( - process_handle, startup_info, + base::Process(process_handle), startup_info, base::MessageLoopProxy::current(), base::Bind(SendReply, channel_.get(), pid)); }
diff --git a/components/nacl/browser/nacl_process_host.cc b/components/nacl/browser/nacl_process_host.cc index c9cc595..e2732041 100644 --- a/components/nacl/browser/nacl_process_host.cc +++ b/components/nacl/browser/nacl_process_host.cc
@@ -1143,7 +1143,6 @@ debug_exception_handler_requested_ = true; base::ProcessId nacl_pid = base::GetProcId(process_->GetData().handle); - base::ProcessHandle temp_handle; // We cannot use process_->GetData().handle because it does not have // the necessary access rights. We open the new handle here rather // than in the NaCl broker process in case the NaCl loader process @@ -1152,21 +1151,20 @@ // but this takes a PID. We need to prevent the NaCl loader's PID // from being reused before DebugActiveProcess() is called, and // holding a process handle open achieves this. - if (!base::OpenProcessHandleWithAccess( - nacl_pid, - base::kProcessAccessQueryInformation | - base::kProcessAccessSuspendResume | - base::kProcessAccessTerminate | - base::kProcessAccessVMOperation | - base::kProcessAccessVMRead | - base::kProcessAccessVMWrite | - base::kProcessAccessDuplicateHandle | - base::kProcessAccessWaitForTermination, - &temp_handle)) { + base::Process process = + base::Process::OpenWithAccess(nacl_pid, + PROCESS_QUERY_INFORMATION | + PROCESS_SUSPEND_RESUME | + PROCESS_TERMINATE | + PROCESS_VM_OPERATION | + PROCESS_VM_READ | + PROCESS_VM_WRITE | + PROCESS_DUP_HANDLE | + SYNCHRONIZE); + if (!process.IsValid()) { LOG(ERROR) << "Failed to get process handle"; return false; } - base::win::ScopedHandle process_handle(temp_handle); attach_debug_exception_handler_reply_msg_.reset(reply_msg); // If the NaCl loader is 64-bit, the process running its debug @@ -1175,11 +1173,11 @@ // the 32-bit browser process to run the debug exception handler. if (RunningOnWOW64()) { return NaClBrokerService::GetInstance()->LaunchDebugExceptionHandler( - weak_factory_.GetWeakPtr(), nacl_pid, process_handle.Get(), + weak_factory_.GetWeakPtr(), nacl_pid, process.Handle(), info); } else { NaClStartDebugExceptionHandlerThread( - process_handle.Take(), info, + process.Pass(), info, base::MessageLoopProxy::current(), base::Bind(&NaClProcessHost::OnDebugExceptionHandlerLaunchedByBroker, weak_factory_.GetWeakPtr()));
diff --git a/components/nacl/common/nacl_debug_exception_handler_win.cc b/components/nacl/common/nacl_debug_exception_handler_win.cc index fdf4a59..7c1e9c0e 100644 --- a/components/nacl/common/nacl_debug_exception_handler_win.cc +++ b/components/nacl/common/nacl_debug_exception_handler_win.cc
@@ -14,11 +14,11 @@ class DebugExceptionHandler : public base::PlatformThread::Delegate { public: DebugExceptionHandler( - base::ProcessHandle nacl_process, + base::Process nacl_process, const std::string& startup_info, const scoped_refptr<base::MessageLoopProxy>& message_loop, const base::Callback<void(bool)>& on_connected) - : nacl_process_(nacl_process), + : nacl_process_(nacl_process.Pass()), startup_info_(startup_info), message_loop_(message_loop), on_connected_(on_connected) {} @@ -30,21 +30,22 @@ // NaClDebugExceptionHandlerRun() receives debug events for the // process. bool attached = false; - int pid = GetProcessId(nacl_process_.Get()); - if (pid == 0) { - LOG(ERROR) << "Invalid process handle"; - } else { + int pid = nacl_process_.Pid(); + if (nacl_process_.IsValid()) { + DCHECK(pid); if (!DebugActiveProcess(pid)) { LOG(ERROR) << "Failed to connect to the process"; } else { attached = true; } + } else { + LOG(ERROR) << "Invalid process handle"; } message_loop_->PostTask(FROM_HERE, base::Bind(on_connected_, attached)); if (attached) { NaClDebugExceptionHandlerRun( - nacl_process_.Get(), + nacl_process_.Handle(), reinterpret_cast<const void*>(startup_info_.data()), startup_info_.size()); } @@ -52,7 +53,7 @@ } private: - base::win::ScopedHandle nacl_process_; + base::Process nacl_process_; std::string startup_info_; const scoped_refptr<base::MessageLoopProxy> message_loop_; base::Callback<void(bool)> on_connected_; @@ -63,14 +64,14 @@ } // namespace void NaClStartDebugExceptionHandlerThread( - base::ProcessHandle nacl_process, + base::Process nacl_process, const std::string& startup_info, const scoped_refptr<base::MessageLoopProxy>& message_loop, const base::Callback<void(bool)>& on_connected) { // The new PlatformThread will take ownership of the // DebugExceptionHandler object, which will delete itself on exit. DebugExceptionHandler* handler = new DebugExceptionHandler( - nacl_process, startup_info, message_loop, on_connected); + nacl_process.Pass(), startup_info, message_loop, on_connected); if (!base::PlatformThread::CreateNonJoinable(0, handler)) { on_connected.Run(false); delete handler;
diff --git a/components/nacl/common/nacl_debug_exception_handler_win.h b/components/nacl/common/nacl_debug_exception_handler_win.h index 5c49d30..b117e6e 100644 --- a/components/nacl/common/nacl_debug_exception_handler_win.h +++ b/components/nacl/common/nacl_debug_exception_handler_win.h
@@ -11,7 +11,7 @@ #include "base/process/process.h" void NaClStartDebugExceptionHandlerThread( - base::ProcessHandle nacl_process, + base::Process nacl_process, const std::string& startup_info, const scoped_refptr<base::MessageLoopProxy>& message_loop, const base::Callback<void(bool)>& on_connected);
diff --git a/components/nacl/loader/DEPS b/components/nacl/loader/DEPS index ec82fff4..5d73078 100644 --- a/components/nacl/loader/DEPS +++ b/components/nacl/loader/DEPS
@@ -32,6 +32,6 @@ "+ppapi/proxy/ppapi_messages.h", # For supporting Mojo in plugins. - "+mojo/edk", "+mojo/nacl", + "+third_party/mojo/src/mojo/edk", ]
diff --git a/components/nacl/loader/nacl_listener.cc b/components/nacl/loader/nacl_listener.cc index d91c8568..ae865f8 100644 --- a/components/nacl/loader/nacl_listener.cc +++ b/components/nacl/loader/nacl_listener.cc
@@ -28,13 +28,13 @@ #include "ipc/ipc_switches.h" #include "ipc/ipc_sync_channel.h" #include "ipc/ipc_sync_message_filter.h" -#include "mojo/edk/embedder/embedder.h" -#include "mojo/edk/embedder/platform_support.h" #include "mojo/nacl/mojo_syscall.h" #include "native_client/src/public/chrome_main.h" #include "native_client/src/public/nacl_app.h" #include "native_client/src/public/nacl_desc.h" #include "native_client/src/public/nacl_file_info.h" +#include "third_party/mojo/src/mojo/edk/embedder/embedder.h" +#include "third_party/mojo/src/mojo/edk/embedder/platform_support.h" #if defined(OS_POSIX) #include "base/file_descriptor_posix.h"
diff --git a/components/nacl/renderer/ppb_nacl_private_impl.cc b/components/nacl/renderer/ppb_nacl_private_impl.cc index 463cd07..3c84afe 100644 --- a/components/nacl/renderer/ppb_nacl_private_impl.cc +++ b/components/nacl/renderer/ppb_nacl_private_impl.cc
@@ -148,7 +148,7 @@ int GetRoutingID(PP_Instance instance) { // Check that we are on the main renderer thread. DCHECK(content::RenderThread::Get()); - content::RendererPpapiHost *host = + content::RendererPpapiHost* host = content::RendererPpapiHost::GetForPPInstance(instance); if (!host) return 0; @@ -358,7 +358,6 @@ const char* alleged_url, const PP_NaClFileInfo* nexe_file_info, PP_Bool uses_nonsfi_mode, - PP_Bool enable_ppapi_dev, PP_NaClAppProcessType pp_process_type, void* imc_handle, PP_CompletionCallback callback) { @@ -374,7 +373,9 @@ IPC::Sender* sender = content::RenderThread::Get(); DCHECK(sender); int routing_id = GetRoutingID(instance); - if (!routing_id) { + NexeLoadManager* load_manager = GetNexeLoadManager(instance); + DCHECK(load_manager); + if (!routing_id || !load_manager) { if (nexe_file_info->handle != PP_kInvalidFileHandle) { base::File closer(nexe_file_info->handle); } @@ -391,7 +392,7 @@ // Conditionally block 'Dev' interfaces. We do this for the NaCl process, so // it's clearer to developers when they are using 'Dev' inappropriately. We // must also check on the trusted side of the proxy. - if (enable_ppapi_dev) + if (load_manager->DevInterfacesEnabled()) perm_bits |= ppapi::PERMISSION_DEV; instance_info.permissions = ppapi::PpapiPermissions::GetForCommandLine(perm_bits); @@ -430,13 +431,6 @@ return; } - NexeLoadManager* load_manager = GetNexeLoadManager(instance); - DCHECK(load_manager); - if (!load_manager) { - PostPPCompletionCallback(callback, PP_ERROR_FAILED); - base::SharedMemory::CloseHandle(launch_result.crash_info_shmem_handle); - return; - } load_manager->set_nonsfi(PP_ToBool(uses_nonsfi_mode)); if (!error_message_string.empty()) { @@ -644,11 +638,11 @@ base::Callback<void(int32_t, bool, PP_FileHandle)> callback) { if (!InitializePnaclResourceHost()) { ppapi::PpapiGlobals::Get()->GetMainThreadMessageLoop()->PostTask( - FROM_HERE, - base::Bind(callback, - static_cast<int32_t>(PP_ERROR_FAILED), - false, - PP_kInvalidFileHandle)); + FROM_HERE, + base::Bind(callback, + static_cast<int32_t>(PP_ERROR_FAILED), + false, + PP_kInvalidFileHandle)); return; } @@ -764,7 +758,7 @@ void DispatchEvent(PP_Instance instance, PP_NaClEventType event_type, - const char *resource_url, + const char* resource_url, PP_Bool length_is_computable, uint64_t loaded_bytes, uint64_t total_bytes) { @@ -776,17 +770,6 @@ DispatchProgressEvent(instance, event); } -void ReportLoadSuccess(PP_Instance instance, - uint64_t loaded_bytes, - uint64_t total_bytes) { - NexeLoadManager* load_manager = GetNexeLoadManager(instance); - if (load_manager) { - load_manager->ReportLoadSuccess(load_manager->program_url(), - loaded_bytes, - total_bytes); - } -} - void ReportLoadError(PP_Instance instance, PP_NaClError error, const char* error_message) { @@ -914,13 +897,6 @@ load_manager->ProcessNaClManifest(program_url); } -PP_Bool DevInterfacesEnabled(PP_Instance instance) { - nacl::NexeLoadManager* load_manager = GetNexeLoadManager(instance); - if (load_manager) - return PP_FromBool(load_manager->DevInterfacesEnabled()); - return PP_FALSE; -} - void DownloadManifestToBufferCompletion(PP_Instance instance, struct PP_CompletionCallback callback, base::Time start_time, @@ -1473,39 +1449,6 @@ time_in_us / 1000)); } -void DidOpenManifestEntry(PP_NaClFileInfo* out_file_info, - PP_CompletionCallback callback, - int32_t pp_error, - const PP_NaClFileInfo& file_info) { - if (pp_error == PP_OK) - *out_file_info = file_info; - callback.func(callback.user_data, pp_error); -} - -void OpenManifestEntry(PP_Instance instance, - PP_Bool is_helper_process, - const char* key, - PP_NaClFileInfo* out_file_info, - PP_CompletionCallback callback) { - std::string url; - PP_PNaClOptions pnacl_options; - pnacl_options.translate = PP_FALSE; - pnacl_options.is_debug = PP_FALSE; - pnacl_options.opt_level = 2; - if (!ManifestResolveKey(instance, - PP_ToBool(is_helper_process), - key, - &url, - &pnacl_options)) { - PostPPCompletionCallback(callback, PP_ERROR_FAILED); - } - - // TODO(teravest): Make a type like PP_NaClFileInfo to use for DownloadFile - // that would close the file handle on destruction. - DownloadFile(instance, url, - base::Bind(&DidOpenManifestEntry, out_file_info, callback)); -} - void SetPNaClStartTime(PP_Instance instance) { NexeLoadManager* load_manager = GetNexeLoadManager(instance); if (load_manager) @@ -1689,7 +1632,6 @@ &GetNumberOfProcessors, &ReportTranslationFinished, &DispatchEvent, - &ReportLoadSuccess, &ReportLoadError, &InstanceCreated, &InstanceDestroyed, @@ -1699,14 +1641,12 @@ &RequestNaClManifest, &GetManifestBaseURL, &ProcessNaClManifest, - &DevInterfacesEnabled, &ManifestGetProgramURL, &GetPNaClResourceInfo, &GetCpuFeatureAttrs, &DownloadNexe, &ReportSelLdrStatus, &LogTranslateTime, - &OpenManifestEntry, &SetPNaClStartTime, &StreamPexe };
diff --git a/components/pairing/bluetooth_controller_pairing_controller.h b/components/pairing/bluetooth_controller_pairing_controller.h index edb79bb..c4a3258d 100644 --- a/components/pairing/bluetooth_controller_pairing_controller.h +++ b/components/pairing/bluetooth_controller_pairing_controller.h
@@ -30,7 +30,7 @@ public device::BluetoothDevice::PairingDelegate { public: BluetoothControllerPairingController(); - virtual ~BluetoothControllerPairingController(); + ~BluetoothControllerPairingController() override; private: void ChangeStage(Stage new_stage); @@ -57,56 +57,48 @@ const std::string& error_message); // ControllerPairingController: - virtual void AddObserver( - ControllerPairingController::Observer* observer) override; - virtual void RemoveObserver( - ControllerPairingController::Observer* observer) override; - virtual Stage GetCurrentStage() override; - virtual void StartPairing() override; - virtual DeviceIdList GetDiscoveredDevices() override; - virtual void ChooseDeviceForPairing(const std::string& device_id) override; - virtual void RepeatDiscovery() override; - virtual std::string GetConfirmationCode() override; - virtual void SetConfirmationCodeIsCorrect(bool correct) override; - virtual void SetHostConfiguration( - bool accepted_eula, - const std::string& lang, - const std::string& timezone, - bool send_reports, - const std::string& keyboard_layout) override; - virtual void OnAuthenticationDone(const std::string& domain, - const std::string& auth_token) override; - virtual void StartSession() override; + void AddObserver(ControllerPairingController::Observer* observer) override; + void RemoveObserver(ControllerPairingController::Observer* observer) override; + Stage GetCurrentStage() override; + void StartPairing() override; + DeviceIdList GetDiscoveredDevices() override; + void ChooseDeviceForPairing(const std::string& device_id) override; + void RepeatDiscovery() override; + std::string GetConfirmationCode() override; + void SetConfirmationCodeIsCorrect(bool correct) override; + void SetHostConfiguration(bool accepted_eula, + const std::string& lang, + const std::string& timezone, + bool send_reports, + const std::string& keyboard_layout) override; + void OnAuthenticationDone(const std::string& domain, + const std::string& auth_token) override; + void StartSession() override; // ProtoDecoder::Observer: - virtual void OnHostStatusMessage( - const pairing_api::HostStatus& message) override; - virtual void OnConfigureHostMessage( + void OnHostStatusMessage(const pairing_api::HostStatus& message) override; + void OnConfigureHostMessage( const pairing_api::ConfigureHost& message) override; - virtual void OnPairDevicesMessage( - const pairing_api::PairDevices& message) override; - virtual void OnCompleteSetupMessage( + void OnPairDevicesMessage(const pairing_api::PairDevices& message) override; + void OnCompleteSetupMessage( const pairing_api::CompleteSetup& message) override; - virtual void OnErrorMessage(const pairing_api::Error& message) override; + void OnErrorMessage(const pairing_api::Error& message) override; // BluetoothAdapter::Observer: - virtual void DeviceAdded(device::BluetoothAdapter* adapter, - device::BluetoothDevice* device) override; - virtual void DeviceRemoved(device::BluetoothAdapter* adapter, - device::BluetoothDevice* device) override; + void DeviceAdded(device::BluetoothAdapter* adapter, + device::BluetoothDevice* device) override; + void DeviceRemoved(device::BluetoothAdapter* adapter, + device::BluetoothDevice* device) override; // device::BluetoothDevice::PairingDelegate: - virtual void RequestPinCode(device::BluetoothDevice* device) override; - virtual void RequestPasskey(device::BluetoothDevice* device) override; - virtual void DisplayPinCode(device::BluetoothDevice* device, - const std::string& pincode) override; - virtual void DisplayPasskey(device::BluetoothDevice* device, - uint32 passkey) override; - virtual void KeysEntered(device::BluetoothDevice* device, - uint32 entered) override; - virtual void ConfirmPasskey(device::BluetoothDevice* device, - uint32 passkey) override; - virtual void AuthorizePairing(device::BluetoothDevice* device) override; + void RequestPinCode(device::BluetoothDevice* device) override; + void RequestPasskey(device::BluetoothDevice* device) override; + void DisplayPinCode(device::BluetoothDevice* device, + const std::string& pincode) override; + void DisplayPasskey(device::BluetoothDevice* device, uint32 passkey) override; + void KeysEntered(device::BluetoothDevice* device, uint32 entered) override; + void ConfirmPasskey(device::BluetoothDevice* device, uint32 passkey) override; + void AuthorizePairing(device::BluetoothDevice* device) override; Stage current_stage_; scoped_refptr<device::BluetoothAdapter> adapter_;
diff --git a/components/pairing/bluetooth_host_pairing_controller.h b/components/pairing/bluetooth_host_pairing_controller.h index 5a1dc744..9c50f5c1 100644 --- a/components/pairing/bluetooth_host_pairing_controller.h +++ b/components/pairing/bluetooth_host_pairing_controller.h
@@ -35,7 +35,7 @@ typedef HostPairingController::Observer Observer; BluetoothHostPairingController(); - virtual ~BluetoothHostPairingController(); + ~BluetoothHostPairingController() override; private: void ChangeStage(Stage new_stage); @@ -62,44 +62,38 @@ const std::string& error_message); // HostPairingController: - virtual void AddObserver(Observer* observer) override; - virtual void RemoveObserver(Observer* observer) override; - virtual Stage GetCurrentStage() override; - virtual void StartPairing() override; - virtual std::string GetDeviceName() override; - virtual std::string GetConfirmationCode() override; - virtual std::string GetEnrollmentDomain() override; - virtual void OnUpdateStatusChanged(UpdateStatus update_status) override; - virtual void OnEnrollmentStatusChanged( - EnrollmentStatus enrollment_status) override; + void AddObserver(Observer* observer) override; + void RemoveObserver(Observer* observer) override; + Stage GetCurrentStage() override; + void StartPairing() override; + std::string GetDeviceName() override; + std::string GetConfirmationCode() override; + std::string GetEnrollmentDomain() override; + void OnUpdateStatusChanged(UpdateStatus update_status) override; + void OnEnrollmentStatusChanged(EnrollmentStatus enrollment_status) override; // ProtoDecoder::Observer: - virtual void OnHostStatusMessage( - const pairing_api::HostStatus& message) override; - virtual void OnConfigureHostMessage( + void OnHostStatusMessage(const pairing_api::HostStatus& message) override; + void OnConfigureHostMessage( const pairing_api::ConfigureHost& message) override; - virtual void OnPairDevicesMessage( - const pairing_api::PairDevices& message) override; - virtual void OnCompleteSetupMessage( + void OnPairDevicesMessage(const pairing_api::PairDevices& message) override; + void OnCompleteSetupMessage( const pairing_api::CompleteSetup& message) override; - virtual void OnErrorMessage(const pairing_api::Error& message) override; + void OnErrorMessage(const pairing_api::Error& message) override; // BluetoothAdapter::Observer: - virtual void AdapterPresentChanged(device::BluetoothAdapter* adapter, - bool present) override; + void AdapterPresentChanged(device::BluetoothAdapter* adapter, + bool present) override; // device::BluetoothDevice::PairingDelegate: - virtual void RequestPinCode(device::BluetoothDevice* device) override; - virtual void RequestPasskey(device::BluetoothDevice* device) override; - virtual void DisplayPinCode(device::BluetoothDevice* device, - const std::string& pincode) override; - virtual void DisplayPasskey(device::BluetoothDevice* device, - uint32 passkey) override; - virtual void KeysEntered(device::BluetoothDevice* device, - uint32 entered) override; - virtual void ConfirmPasskey(device::BluetoothDevice* device, - uint32 passkey) override; - virtual void AuthorizePairing(device::BluetoothDevice* device) override; + void RequestPinCode(device::BluetoothDevice* device) override; + void RequestPasskey(device::BluetoothDevice* device) override; + void DisplayPinCode(device::BluetoothDevice* device, + const std::string& pincode) override; + void DisplayPasskey(device::BluetoothDevice* device, uint32 passkey) override; + void KeysEntered(device::BluetoothDevice* device, uint32 entered) override; + void ConfirmPasskey(device::BluetoothDevice* device, uint32 passkey) override; + void AuthorizePairing(device::BluetoothDevice* device) override; Stage current_stage_; std::string device_name_;
diff --git a/components/pairing/fake_controller_pairing_controller.h b/components/pairing/fake_controller_pairing_controller.h index edb3666f..c1801e2 100644 --- a/components/pairing/fake_controller_pairing_controller.h +++ b/components/pairing/fake_controller_pairing_controller.h
@@ -37,7 +37,7 @@ // * code - 6 digits or empty string. Default: empty string. If strings is // empty, random code is generated. explicit FakeControllerPairingController(const std::string& config); - virtual ~FakeControllerPairingController(); + ~FakeControllerPairingController() override; // Applies given |config| to controller. void ApplyConfig(const std::string& config); @@ -64,24 +64,23 @@ void SetDiscoveryScenario(const DiscoveryScenario& discovery_scenario); // Overridden from ControllerPairingController: - virtual void AddObserver(Observer* observer) override; - virtual void RemoveObserver(Observer* observer) override; - virtual Stage GetCurrentStage() override; - virtual void StartPairing() override; - virtual DeviceIdList GetDiscoveredDevices() override; - virtual void ChooseDeviceForPairing(const std::string& device_id) override; - virtual void RepeatDiscovery() override; - virtual std::string GetConfirmationCode() override; - virtual void SetConfirmationCodeIsCorrect(bool correct) override; - virtual void SetHostConfiguration( - bool accepted_eula, - const std::string& lang, - const std::string& timezone, - bool send_reports, - const std::string& keyboard_layout) override; - virtual void OnAuthenticationDone(const std::string& domain, - const std::string& auth_token) override; - virtual void StartSession() override; + void AddObserver(Observer* observer) override; + void RemoveObserver(Observer* observer) override; + Stage GetCurrentStage() override; + void StartPairing() override; + DeviceIdList GetDiscoveredDevices() override; + void ChooseDeviceForPairing(const std::string& device_id) override; + void RepeatDiscovery() override; + std::string GetConfirmationCode() override; + void SetConfirmationCodeIsCorrect(bool correct) override; + void SetHostConfiguration(bool accepted_eula, + const std::string& lang, + const std::string& timezone, + bool send_reports, + const std::string& keyboard_layout) override; + void OnAuthenticationDone(const std::string& domain, + const std::string& auth_token) override; + void StartSession() override; private: void ChangeStage(Stage new_stage); @@ -91,8 +90,8 @@ void DeviceLost(const std::string& device_id); // Overridden from ui::ControllerPairingController::Observer: - virtual void PairingStageChanged(Stage new_stage) override; - virtual void DiscoveredDevicesListChanged() override; + void PairingStageChanged(Stage new_stage) override; + void DiscoveredDevicesListChanged() override; ObserverList<ControllerPairingController::Observer> observers_; Stage current_stage_;
diff --git a/components/pairing/fake_host_pairing_controller.h b/components/pairing/fake_host_pairing_controller.h index 48335cea..8ef2f4b 100644 --- a/components/pairing/fake_host_pairing_controller.h +++ b/components/pairing/fake_host_pairing_controller.h
@@ -28,7 +28,7 @@ // * device_name - string. Default: "Chromebox-01". // * domain - string. Default: "example.com". explicit FakeHostPairingController(const std::string& config); - virtual ~FakeHostPairingController(); + ~FakeHostPairingController() override; // Applies given |config| to flow. void ApplyConfig(const std::string& config); @@ -38,25 +38,24 @@ void ChangeStageLater(Stage new_stage); // HostPairingController: - virtual void AddObserver(Observer* observer) override; - virtual void RemoveObserver(Observer* observer) override; - virtual Stage GetCurrentStage() override; - virtual void StartPairing() override; - virtual std::string GetDeviceName() override; - virtual std::string GetConfirmationCode() override; - virtual std::string GetEnrollmentDomain() override; - virtual void OnUpdateStatusChanged(UpdateStatus update_status) override; - virtual void OnEnrollmentStatusChanged( - EnrollmentStatus enrollment_status) override; + void AddObserver(Observer* observer) override; + void RemoveObserver(Observer* observer) override; + Stage GetCurrentStage() override; + void StartPairing() override; + std::string GetDeviceName() override; + std::string GetConfirmationCode() override; + std::string GetEnrollmentDomain() override; + void OnUpdateStatusChanged(UpdateStatus update_status) override; + void OnEnrollmentStatusChanged(EnrollmentStatus enrollment_status) override; // HostPairingController::Observer: - virtual void PairingStageChanged(Stage new_stage) override; - virtual void ConfigureHost(bool accepted_eula, - const std::string& lang, - const std::string& timezone, - bool send_reports, - const std::string& keyboard_layout) override; - virtual void EnrollHost(const std::string& auth_token) override; + void PairingStageChanged(Stage new_stage) override; + void ConfigureHost(bool accepted_eula, + const std::string& lang, + const std::string& timezone, + bool send_reports, + const std::string& keyboard_layout) override; + void EnrollHost(const std::string& auth_token) override; ObserverList<Observer> observers_; Stage current_stage_;
diff --git a/components/pairing/shark_connection_listener.h b/components/pairing/shark_connection_listener.h index e2f9b06e..98a7829 100644 --- a/components/pairing/shark_connection_listener.h +++ b/components/pairing/shark_connection_listener.h
@@ -23,19 +23,19 @@ OnConnectedCallback; explicit SharkConnectionListener(OnConnectedCallback callback); - virtual ~SharkConnectionListener(); + ~SharkConnectionListener() override; private: typedef HostPairingController::Stage Stage; // HostPairingController::Observer overrides: - virtual void PairingStageChanged(Stage new_stage) override; - virtual void ConfigureHost(bool accepted_eula, - const std::string& lang, - const std::string& timezone, - bool send_reports, - const std::string& keyboard_layout) override; - virtual void EnrollHost(const std::string& auth_token) override; + void PairingStageChanged(Stage new_stage) override; + void ConfigureHost(bool accepted_eula, + const std::string& lang, + const std::string& timezone, + bool send_reports, + const std::string& keyboard_layout) override; + void EnrollHost(const std::string& auth_token) override; OnConnectedCallback callback_; scoped_ptr<HostPairingController> controller_;
diff --git a/components/password_manager/content/browser/content_credential_manager_dispatcher_unittest.cc b/components/password_manager/content/browser/content_credential_manager_dispatcher_unittest.cc index c484069..42956ad 100644 --- a/components/password_manager/content/browser/content_credential_manager_dispatcher_unittest.cc +++ b/components/password_manager/content/browser/content_credential_manager_dispatcher_unittest.cc
@@ -55,14 +55,20 @@ const std::vector<autofill::PasswordForm*>& federated_forms, base::Callback<void(const password_manager::CredentialInfo&)> callback) override { + // TODO(melandory): Use ScopedVector instead of std::vector in arguments. + // ContentCredentialManagerDispatcher::OnGetPasswordStoreResults contains a + // memory leak because of this. EXPECT_FALSE(local_forms.empty() && federated_forms.empty()); did_prompt_user_to_choose_ = true; ScopedVector<autofill::PasswordForm> local_entries; local_entries.assign(local_forms.begin(), local_forms.end()); ScopedVector<autofill::PasswordForm> federated_entries; federated_entries.assign(federated_forms.begin(), federated_forms.end()); - // TODO(vasilii): Do something clever with |federated_forms|. - password_manager::CredentialInfo info(*local_entries[0]); + password_manager::CredentialInfo info( + local_forms.empty() ? *federated_forms[0] : *local_entries[0], + local_forms.empty() + ? password_manager::CredentialType::CREDENTIAL_TYPE_FEDERATED + : password_manager::CredentialType::CREDENTIAL_TYPE_LOCAL); base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback, info)); return true; @@ -188,7 +194,8 @@ } TEST_F(CredentialManagerDispatcherTest, CredentialManagerOnNotifySignedIn) { - CredentialInfo info(form_); + CredentialInfo info(form_, + password_manager::CredentialType::CREDENTIAL_TYPE_LOCAL); dispatcher()->OnNotifySignedIn(kRequestId, info); const uint32 kMsgID = CredentialManagerMsg_AcknowledgeSignedIn::ID; @@ -215,7 +222,7 @@ } TEST_F(CredentialManagerDispatcherTest, CredentialManagerIncognitoSignedIn) { - CredentialInfo info(form_); + CredentialInfo info(form_, CredentialType::CREDENTIAL_TYPE_LOCAL); client_->set_off_the_record(true); dispatcher()->OnNotifySignedIn(kRequestId, info); @@ -330,4 +337,23 @@ EXPECT_TRUE(client_->did_prompt_user_to_choose()); } +TEST_F(CredentialManagerDispatcherTest, IncognitoRequestCredential) { + client_->set_off_the_record(true); + store_->AddLogin(form_); + + std::vector<GURL> federations; + dispatcher()->OnRequestCredential(kRequestId, true, federations); + + RunAllPendingTasks(); + + const uint32 kMsgID = CredentialManagerMsg_SendCredential::ID; + const IPC::Message* message = + process()->sink().GetFirstMessageMatching(kMsgID); + ASSERT_TRUE(message); + CredentialManagerMsg_SendCredential::Param param; + CredentialManagerMsg_SendCredential::Read(message, ¶m); + EXPECT_EQ(CredentialType::CREDENTIAL_TYPE_EMPTY, get<1>(param).type); + EXPECT_FALSE(client_->did_prompt_user_to_choose()); +} + } // namespace password_manager
diff --git a/components/password_manager/content/browser/credential_manager_dispatcher.cc b/components/password_manager/content/browser/credential_manager_dispatcher.cc index df0aabb..fc7a026 100644 --- a/components/password_manager/content/browser/credential_manager_dispatcher.cc +++ b/components/password_manager/content/browser/credential_manager_dispatcher.cc
@@ -125,6 +125,14 @@ return; } + if (zero_click_only && !IsZeroClickAllowed()) { + web_contents()->GetRenderViewHost()->Send( + new CredentialManagerMsg_SendCredential( + web_contents()->GetRenderViewHost()->GetRoutingID(), request_id, + CredentialInfo())); + return; + } + pending_request_.reset(new PendingRequestParameters( request_id, zero_click_only, web_contents()->GetLastCommittedURL().GetOrigin(), federations)); @@ -182,6 +190,10 @@ return !client_->IsOffTheRecord(); } +bool CredentialManagerDispatcher::IsZeroClickAllowed() const { + return !client_->IsOffTheRecord(); +} + base::WeakPtr<PasswordManagerDriver> CredentialManagerDispatcher::GetDriver() { ContentPasswordManagerDriverFactory* driver_factory = ContentPasswordManagerDriverFactory::FromWebContents(web_contents());
diff --git a/components/password_manager/content/browser/credential_manager_dispatcher.h b/components/password_manager/content/browser/credential_manager_dispatcher.h index f22d1a3..813fa98 100644 --- a/components/password_manager/content/browser/credential_manager_dispatcher.h +++ b/components/password_manager/content/browser/credential_manager_dispatcher.h
@@ -75,6 +75,7 @@ PasswordStore* GetPasswordStore(); bool IsSavingEnabledForCurrentPage() const; + bool IsZeroClickAllowed() const; // Returns the driver for the current main frame. // Virtual for testing.
diff --git a/components/password_manager/content/common/credential_manager_types.cc b/components/password_manager/content/common/credential_manager_types.cc index 8cac746..ea55c068 100644 --- a/components/password_manager/content/common/credential_manager_types.cc +++ b/components/password_manager/content/common/credential_manager_types.cc
@@ -28,20 +28,31 @@ static_cast<const blink::WebLocalCredential&>(credential).password(); } else { DCHECK(credential.isFederatedCredential()); - federation = static_cast<const blink::WebFederatedCredential&>( - credential).federation(); + federation = static_cast<const blink::WebFederatedCredential&>(credential) + .federation(); } } -CredentialInfo::CredentialInfo(const autofill::PasswordForm& form) - : id(form.username_value), +CredentialInfo::CredentialInfo(const autofill::PasswordForm& form, + CredentialType form_type) + : type(form_type), + id(form.username_value), name(form.display_name), avatar(form.avatar_url), password(form.password_value), federation(form.federation_url) { - DCHECK(!password.empty() || !federation.is_empty()); - type = password.empty() ? CredentialType::CREDENTIAL_TYPE_FEDERATED - : CredentialType::CREDENTIAL_TYPE_LOCAL; + switch (form_type) { + case CredentialType::CREDENTIAL_TYPE_EMPTY: + password = base::string16(); + federation = GURL(); + break; + case CredentialType::CREDENTIAL_TYPE_LOCAL: + federation = GURL(); + break; + case CredentialType::CREDENTIAL_TYPE_FEDERATED: + password = base::string16(); + break; + } } CredentialInfo::~CredentialInfo() {
diff --git a/components/password_manager/content/common/credential_manager_types.h b/components/password_manager/content/common/credential_manager_types.h index 2a64acb..324288b 100644 --- a/components/password_manager/content/common/credential_manager_types.h +++ b/components/password_manager/content/common/credential_manager_types.h
@@ -26,6 +26,7 @@ // something reasonably sane. const size_t kMaxFederations = 50u; +// TODO(melandory): Remove unsigned int. enum class CredentialType : unsigned int { CREDENTIAL_TYPE_EMPTY = 0, CREDENTIAL_TYPE_LOCAL, @@ -36,7 +37,8 @@ struct CredentialInfo { CredentialInfo(); explicit CredentialInfo(const blink::WebCredential& credential); - explicit CredentialInfo(const autofill::PasswordForm& form); + explicit CredentialInfo(const autofill::PasswordForm& form, + CredentialType form_type); ~CredentialInfo(); CredentialType type;
diff --git a/components/password_manager/core/browser/login_database.cc b/components/password_manager/core/browser/login_database.cc index c70e650..91b6f9a 100644 --- a/components/password_manager/core/browser/login_database.cc +++ b/components/password_manager/core/browser/login_database.cc
@@ -12,7 +12,6 @@ #include "base/logging.h" #include "base/metrics/histogram.h" #include "base/pickle.h" -#include "base/profiler/scoped_tracker.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/time/time.h" @@ -167,15 +166,9 @@ db_.set_exclusive_locking(); db_.set_restrict_to_user(); - { - // TODO(vadimt): Remove ScopedTracker below once crbug.com/138903 is fixed. - tracked_objects::ScopedTracker tracking_profile( - FROM_HERE_WITH_EXPLICIT_FUNCTION("138903 LoginDatabase::Init db init")); - - if (!db_.Open(db_path_)) { - LOG(WARNING) << "Unable to open the password store database."; - return false; - } + if (!db_.Open(db_path_)) { + LOG(WARNING) << "Unable to open the password store database."; + return false; } sql::Transaction transaction(&db_);
diff --git a/components/password_manager/core/browser/password_form_manager_unittest.cc b/components/password_manager/core/browser/password_form_manager_unittest.cc index bb3f12f..30b7e32 100644 --- a/components/password_manager/core/browser/password_form_manager_unittest.cc +++ b/components/password_manager/core/browser/password_form_manager_unittest.cc
@@ -635,9 +635,8 @@ ASSERT_EQ(1U, passwords[saved_match()->signon_realm].size()); EXPECT_EQ(saved_match()->username_value, passwords[saved_match()->signon_realm][0].username_value); - EXPECT_EQ(0U, - passwords[saved_match()->signon_realm][0] - .other_possible_usernames.size()); + EXPECT_EQ(0U, passwords[saved_match()->signon_realm][0] + .other_possible_usernames.size()); // This time use an alternate username PasswordFormManager manager_alt(&password_manager, &client_with_store, @@ -666,9 +665,8 @@ ASSERT_EQ(1U, passwords[saved_match()->signon_realm].size()); EXPECT_EQ(new_username, passwords[saved_match()->signon_realm][0].username_value); - EXPECT_EQ(0U, - passwords[saved_match()->signon_realm][0] - .other_possible_usernames.size()); + EXPECT_EQ(0U, passwords[saved_match()->signon_realm][0] + .other_possible_usernames.size()); password_store->Shutdown(); } @@ -989,8 +987,9 @@ SimulateFetchMatchingLoginsFromPasswordStore(&manager); SimulateResponseFromPasswordStore(&manager, results); EXPECT_EQ(1u, password_manager.GetLatestBestMatches().size()); - EXPECT_EQ("", password_manager.GetLatestBestMatches().begin() - ->second->original_signon_realm); + EXPECT_EQ("", password_manager.GetLatestBestMatches() + .begin() + ->second->original_signon_realm); } TEST_F(PasswordFormManagerTest, InvalidActionURLsDoNotMatch) { @@ -1257,8 +1256,8 @@ SimulateResponseFromPasswordStore(&form_manager, result); EXPECT_CALL(*client_with_store.mock_driver()->mock_autofill_manager(), - UploadPasswordForm(_, - autofill::ACCOUNT_CREATION_PASSWORD)).Times(1); + UploadPasswordForm(_, autofill::ACCOUNT_CREATION_PASSWORD)) + .Times(1); form_manager.ProvisionallySave( form_to_save, PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES); form_manager.Save();
diff --git a/components/password_manager/core/browser/password_manager_unittest.cc b/components/password_manager/core/browser/password_manager_unittest.cc index ce787d0..22169b0 100644 --- a/components/password_manager/core/browser/password_manager_unittest.cc +++ b/components/password_manager/core/browser/password_manager_unittest.cc
@@ -343,7 +343,8 @@ EXPECT_CALL(client_, PromptUserToSavePasswordPtr(_)).Times(Exactly(0)); EXPECT_CALL(*store_.get(), AddLogin(FormMatches(form))); scoped_ptr<PasswordFormManager> saved_form_manager; - EXPECT_CALL(client_, AutomaticPasswordSavePtr(_)).Times(Exactly(1)) + EXPECT_CALL(client_, AutomaticPasswordSavePtr(_)) + .Times(Exactly(1)) .WillOnce(WithArg<0>(SaveToScopedPtr(&saved_form_manager))); // Now the password manager waits for the navigation to complete. @@ -624,7 +625,8 @@ // Password form should be saved. scoped_ptr<PasswordFormManager> form_to_save; - EXPECT_CALL(client_, PromptUserToSavePasswordPtr(_)).Times(Exactly(1)) + EXPECT_CALL(client_, PromptUserToSavePasswordPtr(_)) + .Times(Exactly(1)) .WillOnce(WithArg<0>(SaveToScopedPtr(&form_to_save))); EXPECT_CALL(*store_.get(), AddLogin(FormMatches(form))).Times(Exactly(0)); @@ -664,7 +666,8 @@ EXPECT_CALL(client_, PromptUserToSavePasswordPtr(_)).Times(Exactly(0)); EXPECT_CALL(*store_.get(), AddLogin(FormMatches(form))); scoped_ptr<PasswordFormManager> saved_form_manager; - EXPECT_CALL(client_, AutomaticPasswordSavePtr(_)).Times(Exactly(1)) + EXPECT_CALL(client_, AutomaticPasswordSavePtr(_)) + .Times(Exactly(1)) .WillOnce(WithArg<0>(SaveToScopedPtr(&saved_form_manager))); // Now the password manager waits for the navigation to complete.
diff --git a/components/password_manager/core/browser/password_store_unittest.cc b/components/password_manager/core/browser/password_store_unittest.cc index 41fa46b..681d042 100644 --- a/components/password_manager/core/browser/password_store_unittest.cc +++ b/components/password_manager/core/browser/password_store_unittest.cc
@@ -167,17 +167,18 @@ // Expect the appropriate replies, as above, in reverse order than we will // issue the queries. Each retires on saturation to avoid matcher spew. - EXPECT_CALL(consumer, - OnGetPasswordStoreResults(ContainsAllPasswordForms(bar_example_expected))) - .WillOnce(WithArg<0>(STLDeleteElements0())).RetiresOnSaturation(); - EXPECT_CALL(consumer, - OnGetPasswordStoreResults( - ContainsAllPasswordForms(accounts_google_expected))) - .WillOnce(WithArg<0>(STLDeleteElements0())).RetiresOnSaturation(); - EXPECT_CALL(consumer, - OnGetPasswordStoreResults( - ContainsAllPasswordForms(www_google_expected))) - .WillOnce(WithArg<0>(STLDeleteElements0())).RetiresOnSaturation(); + EXPECT_CALL(consumer, OnGetPasswordStoreResults( + ContainsAllPasswordForms(bar_example_expected))) + .WillOnce(WithArg<0>(STLDeleteElements0())) + .RetiresOnSaturation(); + EXPECT_CALL(consumer, OnGetPasswordStoreResults( + ContainsAllPasswordForms(accounts_google_expected))) + .WillOnce(WithArg<0>(STLDeleteElements0())) + .RetiresOnSaturation(); + EXPECT_CALL(consumer, OnGetPasswordStoreResults( + ContainsAllPasswordForms(www_google_expected))) + .WillOnce(WithArg<0>(STLDeleteElements0())) + .RetiresOnSaturation(); store->GetLogins(www_google, PasswordStore::ALLOW_PROMPT, &consumer); store->GetLogins(accounts_google, PasswordStore::ALLOW_PROMPT, &consumer);
diff --git a/components/password_manager/core/browser/password_syncable_service.cc b/components/password_manager/core/browser/password_syncable_service.cc index 7818653..8438b2a 100644 --- a/components/password_manager/core/browser/password_syncable_service.cc +++ b/components/password_manager/core/browser/password_syncable_service.cc
@@ -166,12 +166,6 @@ "There are passwords with identical sync tags in the database.")); return merge_result; } - - // Save |sync_processor_| only if reading the PasswordStore succeeded. In case - // of failure Sync shouldn't receive any updates from the PasswordStore. - sync_error_factory_ = sync_error_factory.Pass(); - sync_processor_ = sync_processor.Pass(); - merge_result.set_num_items_before_association(new_local_entries.size()); SyncEntries sync_entries; @@ -204,14 +198,22 @@ } WriteToPasswordStore(sync_entries); + merge_result.set_error( + sync_processor->ProcessSyncChanges(FROM_HERE, updated_db_entries)); + if (merge_result.error().IsSet()) + return merge_result; + merge_result.set_num_items_after_association( merge_result.num_items_before_association() + sync_entries.new_entries.size()); merge_result.set_num_items_added(sync_entries.new_entries.size()); merge_result.set_num_items_modified(sync_entries.updated_entries.size()); merge_result.set_num_items_deleted(sync_entries.deleted_entries.size()); - merge_result.set_error( - sync_processor_->ProcessSyncChanges(FROM_HERE, updated_db_entries)); + + // Save |sync_processor_| only if the whole procedure succeeded. In case of + // failure Sync shouldn't receive any updates from the PasswordStore. + sync_error_factory_ = sync_error_factory.Pass(); + sync_processor_ = sync_processor.Pass(); return merge_result; } @@ -341,6 +343,7 @@ password_store_->NotifyLoginsChanged(changes); } +// static void PasswordSyncableService::CreateOrUpdateEntry( const syncer::SyncData& data, PasswordEntryMap* unmatched_data_from_password_db,
diff --git a/components/password_manager/core/browser/password_syncable_service.h b/components/password_manager/core/browser/password_syncable_service.h index e4a5635..d2cd6fd 100644 --- a/components/password_manager/core/browser/password_syncable_service.h +++ b/components/password_manager/core/browser/password_syncable_service.h
@@ -88,10 +88,11 @@ // Examines |data|, an entry in sync db, and updates |sync_entries| or // |updated_db_entries| accordingly. An element is removed from // |unmatched_data_from_password_db| if its tag is identical to |data|'s. - void CreateOrUpdateEntry(const syncer::SyncData& data, - PasswordEntryMap* unmatched_data_from_password_db, - SyncEntries* sync_entries, - syncer::SyncChangeList* updated_db_entries); + static void CreateOrUpdateEntry( + const syncer::SyncData& data, + PasswordEntryMap* unmatched_data_from_password_db, + SyncEntries* sync_entries, + syncer::SyncChangeList* updated_db_entries); // Calls |operation| for each element in |entries| and appends the changes to // |all_changes|.
diff --git a/components/password_manager/core/browser/password_syncable_service_unittest.cc b/components/password_manager/core/browser/password_syncable_service_unittest.cc index a0279878..ef181292 100644 --- a/components/password_manager/core/browser/password_syncable_service_unittest.cc +++ b/components/password_manager/core/browser/password_syncable_service_unittest.cc
@@ -464,8 +464,8 @@ EXPECT_CALL(*password_store(), FillBlacklistLogins(_)).WillOnce(Return(true)); EXPECT_CALL(*other_service_wrapper.password_store(), FillAutofillableLogins(_)).WillOnce(AppendForm(form2)); - EXPECT_CALL(*other_service_wrapper.password_store(), - FillBlacklistLogins(_)).WillOnce(Return(true)); + EXPECT_CALL(*other_service_wrapper.password_store(), FillBlacklistLogins(_)) + .WillOnce(Return(true)); EXPECT_CALL(*password_store(), AddLoginImpl(PasswordIs(form2))); EXPECT_CALL(*other_service_wrapper.password_store(), @@ -506,17 +506,22 @@ TEST_F(PasswordSyncableServiceTest, FailedReadFromPasswordStore) { scoped_ptr<syncer::SyncErrorFactoryMock> error_factory( new syncer::SyncErrorFactoryMock); + syncer::SyncError error(FROM_HERE, syncer::SyncError::DATATYPE_ERROR, + "Failed to get passwords from store.", + syncer::PASSWORDS); EXPECT_CALL(*password_store(), FillAutofillableLogins(_)) .WillOnce(Return(false)); EXPECT_CALL(*error_factory, CreateAndUploadError(_, _)) - .WillOnce(Return(SyncError())); + .WillOnce(Return(error)); // ActOnPasswordStoreChanges() below shouldn't generate any changes for Sync. // |processor_| will be destroyed in MergeDataAndStartSyncing(). EXPECT_CALL(*processor_, ProcessSyncChanges(_, _)).Times(0); - service()->MergeDataAndStartSyncing(syncer::PASSWORDS, - syncer::SyncDataList(), - processor_.Pass(), - error_factory.Pass()); + syncer::SyncMergeResult result = + service()->MergeDataAndStartSyncing(syncer::PASSWORDS, + syncer::SyncDataList(), + processor_.Pass(), + error_factory.Pass()); + EXPECT_TRUE(result.error().IsSet()); autofill::PasswordForm form; form.signon_realm = kSignonRealm; @@ -525,6 +530,39 @@ service()->ActOnPasswordStoreChanges(list); } +// Start syncing with an error in ProcessSyncChanges. Subsequent password store +// updates shouldn't be propagated to Sync. +TEST_F(PasswordSyncableServiceTest, FailedProcessSyncChanges) { + autofill::PasswordForm form; + form.signon_realm = kSignonRealm; + form.username_value = base::ASCIIToUTF16(kUsername); + form.password_value = base::ASCIIToUTF16(kPassword); + scoped_ptr<syncer::SyncErrorFactoryMock> error_factory( + new syncer::SyncErrorFactoryMock); + syncer::SyncError error(FROM_HERE, syncer::SyncError::DATATYPE_ERROR, + "There is a problem", syncer::PASSWORDS); + EXPECT_CALL(*password_store(), FillAutofillableLogins(_)) + .WillOnce(AppendForm(form)); + EXPECT_CALL(*password_store(), FillBlacklistLogins(_)).WillOnce(Return(true)); + + // ActOnPasswordStoreChanges() below shouldn't generate any changes for Sync. + // |processor_| will be destroyed in MergeDataAndStartSyncing(). + EXPECT_CALL(*processor_, ProcessSyncChanges(_, _)) + .Times(1) + .WillOnce(Return(error)); + syncer::SyncMergeResult result = + service()->MergeDataAndStartSyncing(syncer::PASSWORDS, + syncer::SyncDataList(), + processor_.Pass(), + error_factory.Pass()); + EXPECT_TRUE(result.error().IsSet()); + + form.signon_realm = kSignonRealm2; + PasswordStoreChangeList list; + list.push_back(PasswordStoreChange(PasswordStoreChange::ADD, form)); + service()->ActOnPasswordStoreChanges(list); +} + // Tests that empty forms known to the client and/or the server are deleted. TEST_F(PasswordSyncableServiceTest, MergeEmptyPasswords) { autofill::PasswordForm old_empty_form;
diff --git a/components/plugins/renderer/loadable_plugin_placeholder.cc b/components/plugins/renderer/loadable_plugin_placeholder.cc index ee9c9b5..1ea86a59 100644 --- a/components/plugins/renderer/loadable_plugin_placeholder.cc +++ b/components/plugins/renderer/loadable_plugin_placeholder.cc
@@ -31,6 +31,7 @@ using blink::WebPluginParams; using blink::WebScriptSource; using blink::WebURLRequest; +using content::PluginInstanceThrottler; using content::PluginPowerSaverMode; using content::RenderThread; @@ -44,7 +45,8 @@ render_frame()->RegisterPeripheralPlugin( GURL(GetPluginParams().url).GetOrigin(), base::Bind(&LoadablePluginPlaceholder::DisablePowerSaverForInstance, - weak_factory_.GetWeakPtr())); + weak_factory_.GetWeakPtr(), + PluginInstanceThrottler::UNTHROTTLE_METHOD_BY_WHITELIST)); } #endif @@ -64,17 +66,30 @@ is_blocked_for_power_saver_poster_(false), power_saver_mode_(PluginPowerSaverMode::POWER_SAVER_MODE_ESSENTIAL), allow_loading_(false), + placeholder_was_replaced_(false), hidden_(false), finished_loading_(false), weak_factory_(this) { } LoadablePluginPlaceholder::~LoadablePluginPlaceholder() { +#if defined(ENABLE_PLUGINS) + if (!placeholder_was_replaced_ && !is_blocked_for_prerendering_ && + power_saver_mode_ != PluginPowerSaverMode::POWER_SAVER_MODE_ESSENTIAL) { + PluginInstanceThrottler::RecordUnthrottleMethodMetric( + PluginInstanceThrottler::UNTHROTTLE_METHOD_NEVER); + } +#endif } #if defined(ENABLE_PLUGINS) -void LoadablePluginPlaceholder::DisablePowerSaverForInstance() { +void LoadablePluginPlaceholder::DisablePowerSaverForInstance( + PluginInstanceThrottler::PowerSaverUnthrottleMethod method) { + if (power_saver_mode_ == PluginPowerSaverMode::POWER_SAVER_MODE_ESSENTIAL) + return; + power_saver_mode_ = PluginPowerSaverMode::POWER_SAVER_MODE_ESSENTIAL; + PluginInstanceThrottler::RecordUnthrottleMethodMetric(method); if (is_blocked_for_power_saver_poster_) { is_blocked_for_power_saver_poster_ = false; if (!LoadingBlocked()) @@ -125,6 +140,8 @@ container->reportGeometry(); plugin()->ReplayReceivedData(new_plugin); plugin()->destroy(); + + placeholder_was_replaced_ = true; } void LoadablePluginPlaceholder::HidePlugin() { @@ -239,9 +256,9 @@ // TODO(mmenke): In the case of prerendering, feed into // ChromeContentRendererClient::CreatePlugin instead, to // reduce the chance of future regressions. - scoped_ptr<content::PluginInstanceThrottler> throttler; + scoped_ptr<PluginInstanceThrottler> throttler; #if defined(ENABLE_PLUGINS) - throttler = content::PluginInstanceThrottler::Get( + throttler = PluginInstanceThrottler::Get( render_frame(), GetPluginParams().url, power_saver_mode_); #endif WebPlugin* plugin = render_frame()->CreatePlugin( @@ -254,7 +271,8 @@ #if defined(ENABLE_PLUGINS) // If the user specifically clicks on the plug-in content's placeholder, // disable power saver throttling for this instance. - DisablePowerSaverForInstance(); + DisablePowerSaverForInstance( + PluginInstanceThrottler::UNTHROTTLE_METHOD_BY_CLICK); #endif LoadPlugin(); }
diff --git a/components/plugins/renderer/loadable_plugin_placeholder.h b/components/plugins/renderer/loadable_plugin_placeholder.h index 5f3748f..402fdc7 100644 --- a/components/plugins/renderer/loadable_plugin_placeholder.h +++ b/components/plugins/renderer/loadable_plugin_placeholder.h
@@ -44,7 +44,8 @@ ~LoadablePluginPlaceholder() override; #if defined(ENABLE_PLUGINS) - void DisablePowerSaverForInstance(); + void DisablePowerSaverForInstance( + content::PluginInstanceThrottler::PowerSaverUnthrottleMethod method); #endif void OnLoadBlockedPlugins(const std::string& identifier); @@ -111,6 +112,9 @@ bool allow_loading_; + // True if the placeholder was replaced with the real plugin. + bool placeholder_was_replaced_; + bool hidden_; bool finished_loading_; std::string identifier_;
diff --git a/components/policy.gypi b/components/policy.gypi index 7e0533a4..32845455 100644 --- a/components/policy.gypi +++ b/components/policy.gypi
@@ -311,6 +311,8 @@ 'policy/core/common/cloud/policy_builder.h', 'policy/core/common/configuration_policy_provider_test.cc', 'policy/core/common/configuration_policy_provider_test.h', + 'policy/core/common/fake_async_policy_loader.cc', + 'policy/core/common/fake_async_policy_loader.h', 'policy/core/common/mock_configuration_policy_provider.cc', 'policy/core/common/mock_configuration_policy_provider.h', 'policy/core/common/mock_policy_service.cc', @@ -321,6 +323,12 @@ 'policy/core/common/preferences_mock_mac.h', ], 'conditions': [ + ['OS=="android"', { + 'sources!': [ + 'policy/core/common/fake_async_policy_loader.cc', + 'policy/core/common/fake_async_policy_loader.h', + ], + }], ['chromeos==1', { 'sources!': [ 'policy/core/common/cloud/mock_user_cloud_policy_store.cc',
diff --git a/components/policy/BUILD.gn b/components/policy/BUILD.gn index d8d7c92..9d22fe4 100644 --- a/components/policy/BUILD.gn +++ b/components/policy/BUILD.gn
@@ -188,6 +188,8 @@ "core/common/cloud/policy_builder.h", "core/common/configuration_policy_provider_test.cc", "core/common/configuration_policy_provider_test.h", + "core/common/fake_async_policy_loader.cc", + "core/common/fake_async_policy_loader.h", "core/common/mock_configuration_policy_provider.cc", "core/common/mock_configuration_policy_provider.h", "core/common/mock_policy_service.cc",
diff --git a/components/policy/core/common/async_policy_loader.cc b/components/policy/core/common/async_policy_loader.cc index afe9227..e704673 100644 --- a/components/policy/core/common/async_policy_loader.cc +++ b/components/policy/core/common/async_policy_loader.cc
@@ -28,7 +28,7 @@ } // namespace AsyncPolicyLoader::AsyncPolicyLoader( - scoped_refptr<base::SequencedTaskRunner> task_runner) + const scoped_refptr<base::SequencedTaskRunner>& task_runner) : task_runner_(task_runner), weak_factory_(this) {}
diff --git a/components/policy/core/common/async_policy_loader.h b/components/policy/core/common/async_policy_loader.h index d10608e..16437a87 100644 --- a/components/policy/core/common/async_policy_loader.h +++ b/components/policy/core/common/async_policy_loader.h
@@ -34,7 +34,7 @@ class POLICY_EXPORT AsyncPolicyLoader { public: explicit AsyncPolicyLoader( - scoped_refptr<base::SequencedTaskRunner> task_runner); + const scoped_refptr<base::SequencedTaskRunner>& task_runner); virtual ~AsyncPolicyLoader(); // Gets a SequencedTaskRunner backed by the background thread.
diff --git a/components/policy/core/common/fake_async_policy_loader.cc b/components/policy/core/common/fake_async_policy_loader.cc new file mode 100644 index 0000000..8c441e5 --- /dev/null +++ b/components/policy/core/common/fake_async_policy_loader.cc
@@ -0,0 +1,37 @@ +// Copyright 2015 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/policy/core/common/fake_async_policy_loader.h" + +#include "base/bind.h" +#include "base/location.h" +#include "base/sequenced_task_runner.h" + +namespace policy { + +FakeAsyncPolicyLoader::FakeAsyncPolicyLoader( + const scoped_refptr<base::SequencedTaskRunner>& task_runner) + : AsyncPolicyLoader(task_runner) { +} + +scoped_ptr<PolicyBundle> FakeAsyncPolicyLoader::Load() { + scoped_ptr<PolicyBundle> result(new PolicyBundle()); + result->CopyFrom(policy_bundle_); + return result.Pass(); +} + +void FakeAsyncPolicyLoader::InitOnBackgroundThread() { + // Nothing to do. +} + +void FakeAsyncPolicyLoader::SetPolicies(const PolicyBundle& policy_bundle) { + policy_bundle_.CopyFrom(policy_bundle); +} + +void FakeAsyncPolicyLoader::PostReloadOnBackgroundThread(bool force) { + task_runner()->PostTask(FROM_HERE, base::Bind(&AsyncPolicyLoader::Reload, + base::Unretained(this), force)); +} + +} // namespace policy
diff --git a/components/policy/core/common/fake_async_policy_loader.h b/components/policy/core/common/fake_async_policy_loader.h new file mode 100644 index 0000000..2078e5a --- /dev/null +++ b/components/policy/core/common/fake_async_policy_loader.h
@@ -0,0 +1,53 @@ +// Copyright 2015 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_POLICY_CORE_COMMON_FAKE_ASYNC_POLICY_LOADER_H_ +#define COMPONENTS_POLICY_CORE_COMMON_FAKE_ASYNC_POLICY_LOADER_H_ + +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "components/policy/core/common/async_policy_loader.h" +#include "components/policy/core/common/policy_bundle.h" + +namespace base { +class SequencedTaskRunner; +} // namespace base + +namespace policy { + +// Fake AsyncPolicyLoader for testing with test-controlled policies. +// +// Typical test code would populate the policy contents via calls to +// ClearPolicies and AddPolicies and then notify the rest of the policy +// subsystem of the changes by calling PostReloadOnBackgroundThread. +class FakeAsyncPolicyLoader : public AsyncPolicyLoader { + public: + explicit FakeAsyncPolicyLoader( + const scoped_refptr<base::SequencedTaskRunner>& task_runner); + + // Implementation of virtual methods from AsyncPolicyLoader base class. + scoped_ptr<PolicyBundle> Load() override; + void InitOnBackgroundThread() override; + + // Provides content for the simulated / faked policies. + void SetPolicies(const PolicyBundle& policy_bundle); + + // Notifies the rest of the policy subsystem that policy contents have + // changed. This simulates / fakes a notification that normally would be + // triggered by a FilePathWatcher or (registry)ObjectWatcher in a real loader. + // + // See AsyncPolicyLoader::Reload method for description of the |force| + // parameter. + void PostReloadOnBackgroundThread(bool force); + + private: + PolicyBundle policy_bundle_; + + DISALLOW_COPY_AND_ASSIGN(FakeAsyncPolicyLoader); +}; + +} // namespace policy + +#endif // COMPONENTS_POLICY_CORE_COMMON_FAKE_ASYNC_POLICY_LOADER_H_
diff --git a/components/policy/core/common/proxy_policy_provider.h b/components/policy/core/common/proxy_policy_provider.h index de1ba33..9066b562 100644 --- a/components/policy/core/common/proxy_policy_provider.h +++ b/components/policy/core/common/proxy_policy_provider.h
@@ -41,17 +41,17 @@ public ConfigurationPolicyProvider::Observer { public: ProxyPolicyProvider(); - virtual ~ProxyPolicyProvider(); + ~ProxyPolicyProvider() override; // Updates the provider this proxy delegates to. void SetDelegate(ConfigurationPolicyProvider* delegate); // ConfigurationPolicyProvider: - virtual void Shutdown() override; - virtual void RefreshPolicies() override; + void Shutdown() override; + void RefreshPolicies() override; // ConfigurationPolicyProvider::Observer: - virtual void OnUpdatePolicy(ConfigurationPolicyProvider* provider) override; + void OnUpdatePolicy(ConfigurationPolicyProvider* provider) override; private: ConfigurationPolicyProvider* delegate_;
diff --git a/components/policy/core/common/proxy_policy_provider_unittest.cc b/components/policy/core/common/proxy_policy_provider_unittest.cc index e84a819..09c5da9 100644 --- a/components/policy/core/common/proxy_policy_provider_unittest.cc +++ b/components/policy/core/common/proxy_policy_provider_unittest.cc
@@ -23,7 +23,7 @@ proxy_provider_.AddObserver(&observer_); } - virtual ~ProxyPolicyProviderTest() { + ~ProxyPolicyProviderTest() override { proxy_provider_.RemoveObserver(&observer_); proxy_provider_.Shutdown(); mock_provider_.Shutdown();
diff --git a/components/printing/renderer/print_web_view_helper.cc b/components/printing/renderer/print_web_view_helper.cc index dcd4305..60923cd 100644 --- a/components/printing/renderer/print_web_view_helper.cc +++ b/components/printing/renderer/print_web_view_helper.cc
@@ -829,6 +829,9 @@ if (!IsScriptInitiatedPrintAllowed(frame, user_initiated)) return; + if (delegate_->OverridePrint(frame)) + return; + if (!g_is_preview_enabled_) { Print(frame, blink::WebNode(), true); } else {
diff --git a/components/printing/renderer/print_web_view_helper.h b/components/printing/renderer/print_web_view_helper.h index 5a8242b..273b709 100644 --- a/components/printing/renderer/print_web_view_helper.h +++ b/components/printing/renderer/print_web_view_helper.h
@@ -84,6 +84,10 @@ virtual bool IsOutOfProcessPdfEnabled() = 0; virtual bool IsPrintPreviewEnabled() = 0; + + // Returns true if printing is overridden and the default behavior should be + // skipped for |frame|. + virtual bool OverridePrint(blink::WebLocalFrame* frame) = 0; }; PrintWebViewHelper(content::RenderView* render_view,
diff --git a/components/search_engines/template_url_service.cc b/components/search_engines/template_url_service.cc index 86f6ceea..46c53fe 100644 --- a/components/search_engines/template_url_service.cc +++ b/components/search_engines/template_url_service.cc
@@ -20,6 +20,7 @@ #include "base/strings/string_split.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" +#include "base/time/default_clock.h" #include "base/time/time.h" #include "components/rappor/rappor_service.h" #include "components/search_engines/search_engines_pref_names.h" @@ -198,7 +199,7 @@ load_handle_(0), default_search_provider_(NULL), next_id_(kInvalidTemplateURLID + 1), - time_provider_(&base::Time::Now), + clock_(new base::DefaultClock), models_associated_(false), processing_syncer_changes_(false), dsp_change_origin_(DSP_CHANGE_OTHER), @@ -223,7 +224,7 @@ load_handle_(0), default_search_provider_(NULL), next_id_(kInvalidTemplateURLID + 1), - time_provider_(&base::Time::Now), + clock_(new base::DefaultClock), models_associated_(false), processing_syncer_changes_(false), dsp_change_origin_(DSP_CHANGE_OTHER), @@ -2067,7 +2068,7 @@ data.favicon_url = GURL(); } data.safe_for_autoreplace = false; - data.last_modified = time_provider_(); + data.last_modified = clock_->Now(); return UpdateNoNotify(url, TemplateURL(data)); }
diff --git a/components/search_engines/template_url_service.h b/components/search_engines/template_url_service.h index dda5de4..f93000f5 100644 --- a/components/search_engines/template_url_service.h +++ b/components/search_engines/template_url_service.h
@@ -16,6 +16,7 @@ #include "base/memory/scoped_ptr.h" #include "base/observer_list.h" #include "base/prefs/pref_change_registrar.h" +#include "base/time/clock.h" #include "components/google/core/browser/google_url_tracker.h" #include "components/keyed_service/core/keyed_service.h" #include "components/search_engines/default_search_manager.h" @@ -69,8 +70,6 @@ public: typedef std::map<std::string, std::string> QueryTerms; typedef std::vector<TemplateURL*> TemplateURLVector; - // Type for a static function pointer that acts as a time source. - typedef base::Time(TimeProvider)(); typedef std::map<std::string, syncer::SyncData> SyncDataMap; typedef base::CallbackList<void(void)>::Subscription Subscription; @@ -366,11 +365,7 @@ const syncer::SyncDataList& sync_data); #if defined(UNIT_TEST) - // Sets a different time provider function, such as - // base::MockTimeProvider::StaticNow, for testing calls to base::Time::Now. - void set_time_provider(TimeProvider* time_provider) { - time_provider_ = time_provider; - } + void set_clock(scoped_ptr<base::Clock> clock) { clock_ = clock.Pass(); } #endif private: @@ -706,8 +701,8 @@ // increasing integer that is initialized from the database. TemplateURLID next_id_; - // Function returning current time in base::Time units. - TimeProvider* time_provider_; + // Used to retrieve the current time, in base::Time units. + scoped_ptr<base::Clock> clock_; // Do we have an active association between the TemplateURLs and sync models? // Set in MergeDataAndStartSyncing, reset in StopSyncing. While this is not
diff --git a/components/search_engines/template_url_service_unittest.cc b/components/search_engines/template_url_service_unittest.cc index ad474e7..368496c 100644 --- a/components/search_engines/template_url_service_unittest.cc +++ b/components/search_engines/template_url_service_unittest.cc
@@ -2,17 +2,20 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "components/search_engines/template_url_service.h" + #include "base/bind.h" #include "base/bind_helpers.h" #include "base/callback.h" #include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_vector.h" #include "base/run_loop.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "base/task/cancelable_task_tracker.h" -#include "base/test/mock_time_provider.h" +#include "base/test/simple_test_clock.h" #include "base/threading/thread.h" #include "base/time/time.h" #include "chrome/browser/history/history_service.h" @@ -24,15 +27,12 @@ #include "components/search_engines/search_terms_data.h" #include "components/search_engines/template_url.h" #include "components/search_engines/template_url_prepopulate_data.h" -#include "components/search_engines/template_url_service.h" #include "content/public/test/test_browser_thread_bundle.h" #include "testing/gtest/include/gtest/gtest.h" using base::ASCIIToUTF16; using base::Time; using base::TimeDelta; -using ::testing::Return; -using ::testing::StrictMock; namespace { @@ -150,6 +150,10 @@ // Verifies the two TemplateURLs are equal. void AssertEquals(const TemplateURL& expected, const TemplateURL& actual); + // Verifies the two timestamps are equal, within the expected degree of + // precision. + void AssertTimesEqual(const base::Time& expected, const base::Time& actual); + // Create an URL that appears to have been prepopulated, but won't be in the // current data. The caller owns the returned TemplateURL*. TemplateURL* CreatePreloadedTemplateURL(bool safe_for_autoreplace, @@ -227,12 +231,20 @@ ASSERT_EQ(expected.input_encodings(), actual.input_encodings()); ASSERT_EQ(expected.id(), actual.id()); ASSERT_EQ(expected.date_created(), actual.date_created()); - ASSERT_EQ(expected.last_modified(), actual.last_modified()); + AssertTimesEqual(expected.last_modified(), actual.last_modified()); ASSERT_EQ(expected.sync_guid(), actual.sync_guid()); ASSERT_EQ(expected.search_terms_replacement_key(), actual.search_terms_replacement_key()); } +void TemplateURLServiceTest::AssertTimesEqual(const base::Time& expected, + const base::Time& actual) { + // Because times are stored with a granularity of one second, there is a loss + // of precision when serializing and deserializing the timestamps. Hence, only + // expect timestamps to be equal to within one second of one another. + ASSERT_LT((expected - actual).magnitude(), base::TimeDelta::FromSeconds(1)); +} + TemplateURL* TemplateURLServiceTest::CreatePreloadedTemplateURL( bool safe_for_autoreplace, int prepopulate_id) { @@ -305,11 +317,11 @@ NULL)); // We expect the last_modified time to be updated to the present time on an - // explicit reset. We have to set up the expectation here because ResetModel - // resets the TimeProvider in the TemplateURLService. - StrictMock<base::MockTimeProvider> mock_time; - model()->set_time_provider(&base::MockTimeProvider::StaticNow); - EXPECT_CALL(mock_time, Now()).WillOnce(Return(base::Time::FromDoubleT(1337))); + // explicit reset. + base::Time now = base::Time::Now(); + scoped_ptr<base::SimpleTestClock> clock(new base::SimpleTestClock); + clock->SetNow(now); + model()->set_clock(clock.Pass()); // Mutate an element and verify it succeeded. model()->ResetTemplateURL(loaded_url, ASCIIToUTF16("a"), ASCIIToUTF16("b"), @@ -330,7 +342,7 @@ AssertEquals(*cloned_url, *loaded_url); // We changed a TemplateURL in the service, so ensure that the time was // updated. - ASSERT_EQ(base::Time::FromDoubleT(1337), loaded_url->last_modified()); + AssertTimesEqual(now, loaded_url->last_modified()); // Remove an element and verify it succeeded. model()->Remove(loaded_url); @@ -620,9 +632,10 @@ VerifyObserverCount(1); base::RunLoop().RunUntilIdle(); - StrictMock<base::MockTimeProvider> mock_time; - model()->set_time_provider(&base::MockTimeProvider::StaticNow); - EXPECT_CALL(mock_time, Now()).WillOnce(Return(base::Time::FromDoubleT(1337))); + base::Time now = base::Time::Now(); + scoped_ptr<base::SimpleTestClock> clock(new base::SimpleTestClock); + clock->SetNow(now); + model()->set_clock(clock.Pass()); // Reset the short name, keyword, url and make sure it takes. const base::string16 new_short_name(ASCIIToUTF16("a")); @@ -646,7 +659,7 @@ const TemplateURL* read_url = model()->GetTemplateURLForKeyword(new_keyword); ASSERT_TRUE(read_url); AssertEquals(*cloned_url, *read_url); - ASSERT_EQ(base::Time::FromDoubleT(1337), read_url->last_modified()); + AssertTimesEqual(now, read_url->last_modified()); } TEST_F(TemplateURLServiceTest, DefaultSearchProvider) {
diff --git a/components/storage_monitor/storage_monitor_chromeos.h b/components/storage_monitor/storage_monitor_chromeos.h index 726f0dc5..bfbeed6b 100644 --- a/components/storage_monitor/storage_monitor_chromeos.h +++ b/components/storage_monitor/storage_monitor_chromeos.h
@@ -33,41 +33,37 @@ // Should only be called by browser start up code. // Use StorageMonitor::GetInstance() instead. StorageMonitorCros(); - virtual ~StorageMonitorCros(); + ~StorageMonitorCros() override; // Sets up disk listeners and issues notifications for any discovered // mount points. Sets up MTP manager and listeners. - virtual void Init() override; + void Init() override; protected: void SetMediaTransferProtocolManagerForTest( device::MediaTransferProtocolManager* test_manager); // chromeos::disks::DiskMountManager::Observer implementation. - virtual void OnDiskEvent( + void OnDiskEvent( chromeos::disks::DiskMountManager::DiskEvent event, const chromeos::disks::DiskMountManager::Disk* disk) override; - virtual void OnDeviceEvent( - chromeos::disks::DiskMountManager::DeviceEvent event, - const std::string& device_path) override; - virtual void OnMountEvent( - chromeos::disks::DiskMountManager::MountEvent event, - chromeos::MountError error_code, - const chromeos::disks::DiskMountManager::MountPointInfo& mount_info) - override; - virtual void OnFormatEvent( - chromeos::disks::DiskMountManager::FormatEvent event, - chromeos::FormatError error_code, - const std::string& device_path) override; + void OnDeviceEvent(chromeos::disks::DiskMountManager::DeviceEvent event, + const std::string& device_path) override; + void OnMountEvent(chromeos::disks::DiskMountManager::MountEvent event, + chromeos::MountError error_code, + const chromeos::disks::DiskMountManager::MountPointInfo& + mount_info) override; + void OnFormatEvent(chromeos::disks::DiskMountManager::FormatEvent event, + chromeos::FormatError error_code, + const std::string& device_path) override; // StorageMonitor implementation. - virtual bool GetStorageInfoForPath(const base::FilePath& path, - StorageInfo* device_info) const override; - virtual void EjectDevice( - const std::string& device_id, - base::Callback<void(EjectStatus)> callback) override; - virtual device::MediaTransferProtocolManager* - media_transfer_protocol_manager() override; + bool GetStorageInfoForPath(const base::FilePath& path, + StorageInfo* device_info) const override; + void EjectDevice(const std::string& device_id, + base::Callback<void(EjectStatus)> callback) override; + device::MediaTransferProtocolManager* media_transfer_protocol_manager() + override; private: // Mapping of mount path to removable mass storage info.
diff --git a/components/storage_monitor/storage_monitor_chromeos_unittest.cc b/components/storage_monitor/storage_monitor_chromeos_unittest.cc index e6838c13..72111be 100644 --- a/components/storage_monitor/storage_monitor_chromeos_unittest.cc +++ b/components/storage_monitor/storage_monitor_chromeos_unittest.cc
@@ -59,27 +59,27 @@ public: TestStorageMonitorCros() {} - virtual ~TestStorageMonitorCros() {} + ~TestStorageMonitorCros() override {} - virtual void Init() override { + void Init() override { SetMediaTransferProtocolManagerForTest( new TestMediaTransferProtocolManagerLinux()); StorageMonitorCros::Init(); } - virtual void OnMountEvent(DiskMountManager::MountEvent event, + void OnMountEvent( + DiskMountManager::MountEvent event, chromeos::MountError error_code, const DiskMountManager::MountPointInfo& mount_info) override { StorageMonitorCros::OnMountEvent(event, error_code, mount_info); } - virtual bool GetStorageInfoForPath(const base::FilePath& path, - StorageInfo* device_info) const override { + bool GetStorageInfoForPath(const base::FilePath& path, + StorageInfo* device_info) const override { return StorageMonitorCros::GetStorageInfoForPath(path, device_info); } - virtual void EjectDevice( - const std::string& device_id, - base::Callback<void(EjectStatus)> callback) override { + void EjectDevice(const std::string& device_id, + base::Callback<void(EjectStatus)> callback) override { StorageMonitorCros::EjectDevice(device_id, callback); } @@ -91,14 +91,14 @@ class StorageMonitorCrosTest : public testing::Test { public: StorageMonitorCrosTest(); - virtual ~StorageMonitorCrosTest(); + ~StorageMonitorCrosTest() override; void EjectNotify(StorageMonitor::EjectStatus status); protected: // testing::Test: - virtual void SetUp() override; - virtual void TearDown() override; + void SetUp() override; + void TearDown() override; void MountDevice(chromeos::MountError error_code, const DiskMountManager::MountPointInfo& mount_info,
diff --git a/components/test/data/component_updater/OWNERS b/components/test/data/update_client/OWNERS similarity index 100% rename from components/test/data/component_updater/OWNERS rename to components/test/data/update_client/OWNERS
diff --git a/components/test/data/component_updater/binary_bsdiff_patch.bin b/components/test/data/update_client/binary_bsdiff_patch.bin similarity index 100% rename from components/test/data/component_updater/binary_bsdiff_patch.bin rename to components/test/data/update_client/binary_bsdiff_patch.bin Binary files differ
diff --git a/components/test/data/component_updater/binary_courgette_patch.bin b/components/test/data/update_client/binary_courgette_patch.bin similarity index 100% rename from components/test/data/component_updater/binary_courgette_patch.bin rename to components/test/data/update_client/binary_courgette_patch.bin Binary files differ
diff --git a/components/test/data/component_updater/binary_input.bin b/components/test/data/update_client/binary_input.bin similarity index 100% rename from components/test/data/component_updater/binary_input.bin rename to components/test/data/update_client/binary_input.bin Binary files differ
diff --git a/components/test/data/component_updater/binary_output.bin b/components/test/data/update_client/binary_output.bin similarity index 100% rename from components/test/data/component_updater/binary_output.bin rename to components/test/data/update_client/binary_output.bin Binary files differ
diff --git a/components/test/data/component_updater/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc.pem b/components/test/data/update_client/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc.pem similarity index 100% rename from components/test/data/component_updater/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc.pem rename to components/test/data/update_client/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc.pem
diff --git a/components/test/data/component_updater/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_1/a_changing_binary_file b/components/test/data/update_client/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_1/a_changing_binary_file old mode 100644 new mode 100755 similarity index 100% rename from components/test/data/component_updater/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_1/a_changing_binary_file rename to components/test/data/update_client/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_1/a_changing_binary_file Binary files differ
diff --git a/components/test/data/component_updater/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_1/a_changing_text_file b/components/test/data/update_client/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_1/a_changing_text_file similarity index 100% rename from components/test/data/component_updater/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_1/a_changing_text_file rename to components/test/data/update_client/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_1/a_changing_text_file
diff --git a/components/test/data/component_updater/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_1/a_static_text_file b/components/test/data/update_client/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_1/a_static_text_file similarity index 100% rename from components/test/data/component_updater/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_1/a_static_text_file rename to components/test/data/update_client/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_1/a_static_text_file
diff --git a/components/test/data/component_updater/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_1/manifest.json b/components/test/data/update_client/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_1/manifest.json similarity index 100% rename from components/test/data/component_updater/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_1/manifest.json rename to components/test/data/update_client/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_1/manifest.json
diff --git a/components/test/data/component_updater/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_1to2/commands.json b/components/test/data/update_client/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_1to2/commands.json similarity index 100% rename from components/test/data/component_updater/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_1to2/commands.json rename to components/test/data/update_client/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_1to2/commands.json
diff --git a/components/test/data/component_updater/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_1to2/f0 b/components/test/data/update_client/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_1to2/f0 similarity index 100% rename from components/test/data/component_updater/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_1to2/f0 rename to components/test/data/update_client/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_1to2/f0
diff --git a/components/test/data/component_updater/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_1to2/f1 b/components/test/data/update_client/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_1to2/f1 similarity index 100% rename from components/test/data/component_updater/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_1to2/f1 rename to components/test/data/update_client/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_1to2/f1 Binary files differ
diff --git a/components/test/data/component_updater/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_1to2/f2 b/components/test/data/update_client/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_1to2/f2 similarity index 100% rename from components/test/data/component_updater/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_1to2/f2 rename to components/test/data/update_client/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_1to2/f2
diff --git a/components/test/data/component_updater/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_1to2_bad/commands.json b/components/test/data/update_client/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_1to2_bad/commands.json similarity index 100% rename from components/test/data/component_updater/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_1to2_bad/commands.json rename to components/test/data/update_client/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_1to2_bad/commands.json
diff --git a/components/test/data/component_updater/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_1to2_bad/f1 b/components/test/data/update_client/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_1to2_bad/f1 similarity index 100% rename from components/test/data/component_updater/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_1to2_bad/f1 rename to components/test/data/update_client/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_1to2_bad/f1
diff --git a/components/test/data/component_updater/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_1to2_bad/f2 b/components/test/data/update_client/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_1to2_bad/f2 similarity index 100% rename from components/test/data/component_updater/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_1to2_bad/f2 rename to components/test/data/update_client/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_1to2_bad/f2
diff --git a/components/test/data/component_updater/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_1to2_bad/f3 b/components/test/data/update_client/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_1to2_bad/f3 similarity index 100% rename from components/test/data/component_updater/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_1to2_bad/f3 rename to components/test/data/update_client/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_1to2_bad/f3 Binary files differ
diff --git a/components/test/data/component_updater/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_2/a_changing_binary_file b/components/test/data/update_client/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_2/a_changing_binary_file old mode 100644 new mode 100755 similarity index 100% rename from components/test/data/component_updater/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_2/a_changing_binary_file rename to components/test/data/update_client/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_2/a_changing_binary_file Binary files differ
diff --git a/components/test/data/component_updater/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_2/a_changing_text_file b/components/test/data/update_client/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_2/a_changing_text_file similarity index 100% rename from components/test/data/component_updater/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_2/a_changing_text_file rename to components/test/data/update_client/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_2/a_changing_text_file
diff --git a/components/test/data/component_updater/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_2/a_static_text_file b/components/test/data/update_client/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_2/a_static_text_file similarity index 100% rename from components/test/data/component_updater/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_2/a_static_text_file rename to components/test/data/update_client/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_2/a_static_text_file
diff --git a/components/test/data/component_updater/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_2/manifest.json b/components/test/data/update_client/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_2/manifest.json similarity index 100% rename from components/test/data/component_updater/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_2/manifest.json rename to components/test/data/update_client/ihfokbkgjpifnbbojhneepfflplebdkc/ihfokbkgjpifnbbojhneepfflplebdkc_2/manifest.json
diff --git a/components/test/data/component_updater/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx b/components/test/data/update_client/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx similarity index 100% rename from components/test/data/component_updater/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx rename to components/test/data/update_client/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx Binary files differ
diff --git a/components/test/data/component_updater/ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx b/components/test/data/update_client/ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx similarity index 100% rename from components/test/data/component_updater/ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx rename to components/test/data/update_client/ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx Binary files differ
diff --git a/components/test/data/component_updater/ihfokbkgjpifnbbojhneepfflplebdkc_1to2_bad.crx b/components/test/data/update_client/ihfokbkgjpifnbbojhneepfflplebdkc_1to2_bad.crx similarity index 100% rename from components/test/data/component_updater/ihfokbkgjpifnbbojhneepfflplebdkc_1to2_bad.crx rename to components/test/data/update_client/ihfokbkgjpifnbbojhneepfflplebdkc_1to2_bad.crx Binary files differ
diff --git a/components/test/data/component_updater/ihfokbkgjpifnbbojhneepfflplebdkc_2.crx b/components/test/data/update_client/ihfokbkgjpifnbbojhneepfflplebdkc_2.crx similarity index 100% rename from components/test/data/component_updater/ihfokbkgjpifnbbojhneepfflplebdkc_2.crx rename to components/test/data/update_client/ihfokbkgjpifnbbojhneepfflplebdkc_2.crx Binary files differ
diff --git a/components/test/data/component_updater/jebgalgnebhfojomionfpkfelancnnkf.crx b/components/test/data/update_client/jebgalgnebhfojomionfpkfelancnnkf.crx similarity index 100% rename from components/test/data/component_updater/jebgalgnebhfojomionfpkfelancnnkf.crx rename to components/test/data/update_client/jebgalgnebhfojomionfpkfelancnnkf.crx Binary files differ
diff --git a/components/test/data/component_updater/jebgalgnebhfojomionfpkfelancnnkf.pem b/components/test/data/update_client/jebgalgnebhfojomionfpkfelancnnkf.pem similarity index 100% rename from components/test/data/component_updater/jebgalgnebhfojomionfpkfelancnnkf.pem rename to components/test/data/update_client/jebgalgnebhfojomionfpkfelancnnkf.pem
diff --git a/components/test/data/component_updater/jebgalgnebhfojomionfpkfelancnnkf/component1.dll b/components/test/data/update_client/jebgalgnebhfojomionfpkfelancnnkf/component1.dll similarity index 100% rename from components/test/data/component_updater/jebgalgnebhfojomionfpkfelancnnkf/component1.dll rename to components/test/data/update_client/jebgalgnebhfojomionfpkfelancnnkf/component1.dll Binary files differ
diff --git a/components/test/data/component_updater/jebgalgnebhfojomionfpkfelancnnkf/manifest.json b/components/test/data/update_client/jebgalgnebhfojomionfpkfelancnnkf/manifest.json similarity index 100% rename from components/test/data/component_updater/jebgalgnebhfojomionfpkfelancnnkf/manifest.json rename to components/test/data/update_client/jebgalgnebhfojomionfpkfelancnnkf/manifest.json
diff --git a/components/test/data/component_updater/updatecheck_diff_reply_1.xml b/components/test/data/update_client/updatecheck_diff_reply_1.xml similarity index 100% rename from components/test/data/component_updater/updatecheck_diff_reply_1.xml rename to components/test/data/update_client/updatecheck_diff_reply_1.xml
diff --git a/components/test/data/component_updater/updatecheck_diff_reply_2.xml b/components/test/data/update_client/updatecheck_diff_reply_2.xml similarity index 100% rename from components/test/data/component_updater/updatecheck_diff_reply_2.xml rename to components/test/data/update_client/updatecheck_diff_reply_2.xml
diff --git a/components/test/data/component_updater/updatecheck_diff_reply_3.xml b/components/test/data/update_client/updatecheck_diff_reply_3.xml similarity index 100% rename from components/test/data/component_updater/updatecheck_diff_reply_3.xml rename to components/test/data/update_client/updatecheck_diff_reply_3.xml
diff --git a/components/test/data/component_updater/updatecheck_reply_1.xml b/components/test/data/update_client/updatecheck_reply_1.xml similarity index 100% rename from components/test/data/component_updater/updatecheck_reply_1.xml rename to components/test/data/update_client/updatecheck_reply_1.xml
diff --git a/components/test/data/component_updater/updatecheck_reply_2.xml b/components/test/data/update_client/updatecheck_reply_2.xml similarity index 100% rename from components/test/data/component_updater/updatecheck_reply_2.xml rename to components/test/data/update_client/updatecheck_reply_2.xml
diff --git a/components/test/data/component_updater/updatecheck_reply_3.xml b/components/test/data/update_client/updatecheck_reply_3.xml similarity index 100% rename from components/test/data/component_updater/updatecheck_reply_3.xml rename to components/test/data/update_client/updatecheck_reply_3.xml
diff --git a/components/test/data/component_updater/updatecheck_reply_empty b/components/test/data/update_client/updatecheck_reply_empty similarity index 100% rename from components/test/data/component_updater/updatecheck_reply_empty rename to components/test/data/update_client/updatecheck_reply_empty
diff --git a/components/test/data/component_updater/updatecheck_reply_noupdate.xml b/components/test/data/update_client/updatecheck_reply_noupdate.xml similarity index 100% rename from components/test/data/component_updater/updatecheck_reply_noupdate.xml rename to components/test/data/update_client/updatecheck_reply_noupdate.xml
diff --git a/components/timers/rtc_alarm.h b/components/timers/rtc_alarm.h index bbde8c7..8cc06bd4 100644 --- a/components/timers/rtc_alarm.h +++ b/components/timers/rtc_alarm.h
@@ -48,7 +48,7 @@ protected: // Needs to be protected because AlarmTimer::Delegate is a refcounted class. - virtual ~RtcAlarm(); + ~RtcAlarm() override; private: // Actually performs the system calls to set up the timer. This must be
diff --git a/components/update_client.gypi b/components/update_client.gypi index 58640eb7..7e8cda1 100644 --- a/components/update_client.gypi +++ b/components/update_client.gypi
@@ -5,19 +5,75 @@ { 'targets': [ { + # GN version: //components/update_client 'target_name': 'update_client', 'type': 'static_library', + 'dependencies': [ + '../base/base.gyp:base', + '../courgette/courgette.gyp:courgette_lib', + '../crypto/crypto.gyp:crypto', + '../third_party/libxml/libxml.gyp:libxml', + '../third_party/zlib/google/zip.gyp:zip', + '../net/net.gyp:net', + '../url/url.gyp:url_lib', + 'crx_file', + ], + 'include_dirs': [ '..', ], - 'dependencies': [ - '../base/base.gyp:base', - ], 'sources': [ + 'update_client/background_downloader_win.cc', + 'update_client/background_downloader_win.h', + 'update_client/component_patcher.cc', + 'update_client/component_patcher.h', + 'update_client/component_patcher_operation.cc', + 'update_client/component_patcher_operation.h', + 'update_client/component_unpacker.cc', + 'update_client/component_unpacker.h', + 'update_client/ping_manager.cc', + 'update_client/ping_manager.h', + 'update_client/crx_update_item.h', + 'update_client/crx_downloader.cc', + 'update_client/crx_downloader.h', + 'update_client/request_sender.cc', + 'update_client/request_sender.h', + 'update_client/update_checker.cc', + 'update_client/update_checker.h', + 'update_client/update_client.cc', + 'update_client/update_client.h', + 'update_client/update_response.cc', + 'update_client/update_response.h', 'update_client/update_query_params.cc', 'update_client/update_query_params.h', 'update_client/update_query_params_delegate.cc', 'update_client/update_query_params_delegate.h', + 'update_client/url_fetcher_downloader.cc', + 'update_client/url_fetcher_downloader.h', + 'update_client/utils.cc', + 'update_client/utils.h', + ], + }, + { + # GN version: //components/update_client:test_support + 'target_name': 'update_client_test_support', + 'type': 'static_library', + 'dependencies': [ + 'update_client', + '../testing/gmock.gyp:gmock', + '../testing/gtest.gyp:gtest', + ], + + 'include_dirs': [ + '..', + ], + 'sources': [ + 'update_client/test/test_configurator.cc', + 'update_client/test/test_configurator.h', + 'update_client/test/test_installer.cc', + 'update_client/test/test_installer.h', + 'update_client/test/url_request_post_interceptor.cc', + 'update_client/test/url_request_post_interceptor.h', ], }, ],
diff --git a/components/update_client/BUILD.gn b/components/update_client/BUILD.gn index d51bd9d..8dd5ef81 100644 --- a/components/update_client/BUILD.gn +++ b/components/update_client/BUILD.gn
@@ -4,13 +4,89 @@ source_set("update_client") { sources = [ + "background_downloader_win.cc", + "background_downloader_win.h", + "component_patcher.cc", + "component_patcher.h", + "component_patcher_operation.cc", + "component_patcher_operation.h", + "component_unpacker.cc", + "component_unpacker.h", + "ping_manager.cc", + "ping_manager.h", + "utils.cc", + "utils.h", + "crx_update_item.h", + "crx_downloader.cc", + "crx_downloader.h", + "request_sender.cc", + "request_sender.h", + "update_checker.cc", + "update_checker.h", + "update_client.cc", + "update_client.h", "update_query_params.cc", "update_query_params.h", "update_query_params_delegate.cc", "update_query_params_delegate.h", + "update_response.cc", + "update_response.h", + "url_fetcher_downloader.cc", + "url_fetcher_downloader.h", ] deps = [ "//base", + "//components/crx_file", + "//courgette:courgette_lib", + "//crypto", + "//third_party/libxml", + "//third_party/zlib:zip", + "//net", + "//url", + ] +} + +source_set("test_support") { + testonly = true + sources = [ + "test/test_configurator.cc", + "test/test_configurator.h", + "test/test_installer.cc", + "test/test_installer.h", + "test/url_request_post_interceptor.cc", + "test/url_request_post_interceptor.h", + ] + + deps = [ + ":update_client", + "//base", + "//net:test_support", + "//testing/gtest", + "//testing/gmock", + "//url", + ] +} + +source_set("unit_tests") { + testonly = true + sources = [ + "test/component_patcher_unittest.cc", + "test/ping_manager_unittest.cc", + "test/crx_downloader_unittest.cc", + "test/request_sender_unittest.cc", + "test/update_checker_unittest.cc", + "test/update_response_unittest.cc", + ] + + deps = [ + ":update_client", + ":test_support", + "//base", + "//courgette:courgette_lib", + "//net:test_support", + "//testing/gtest", + "//testing/gmock", + "//third_party/libxml", ] }
diff --git a/components/update_client/DEPS b/components/update_client/DEPS index beabace2e..79e03498 100644 --- a/components/update_client/DEPS +++ b/components/update_client/DEPS
@@ -1,4 +1,12 @@ include_rules = [ "+base", + "+components/crx_file", + "+courgette", + "+crypto", + "+libxml", + "+net", + "+ui/base/win", + "+third_party/libxml", + "+third_party/zlib", "+testing", ]
diff --git a/components/component_updater/background_downloader_win.cc b/components/update_client/background_downloader_win.cc similarity index 95% rename from components/component_updater/background_downloader_win.cc rename to components/update_client/background_downloader_win.cc index 2e9b997..536fafd3 100644 --- a/components/component_updater/background_downloader_win.cc +++ b/components/update_client/background_downloader_win.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 "components/component_updater/background_downloader_win.h" +#include "components/update_client/background_downloader_win.h" #include <atlbase.h> #include <atlcom.h> @@ -20,7 +20,7 @@ #include "base/single_thread_task_runner.h" #include "base/strings/sys_string_conversions.h" #include "base/win/scoped_co_mem.h" -#include "components/component_updater/component_updater_utils.h" +#include "components/update_client/utils.h" #include "ui/base/win/atl_module.h" #include "url/gurl.h" @@ -93,7 +93,7 @@ // Last, after completing a job, irrespective of the outcome, the jobs older // than a week are proactively cleaned up. -namespace component_updater { +namespace update_client { namespace { @@ -141,7 +141,7 @@ // Returns the files in a BITS job. HRESULT GetFilesInJob(IBackgroundCopyJob* job, - std::vector<ScopedComPtr<IBackgroundCopyFile> >* files) { + std::vector<ScopedComPtr<IBackgroundCopyFile>>* files) { ScopedComPtr<IEnumBackgroundCopyFiles> enum_files; HRESULT hr = job->EnumFiles(enum_files.Receive()); if (FAILED(hr)) @@ -259,7 +259,7 @@ template <class Predicate> HRESULT FindBitsJobIf(Predicate pred, IBackgroundCopyManager* bits_manager, - std::vector<ScopedComPtr<IBackgroundCopyJob> >* jobs) { + std::vector<ScopedComPtr<IBackgroundCopyJob>>* jobs) { ScopedComPtr<IEnumBackgroundCopyJobs> enum_jobs; HRESULT hr = bits_manager->EnumJobs(0, enum_jobs.Receive()); if (FAILED(hr)) @@ -317,7 +317,7 @@ bool JobFileUrlEqual::operator()(IBackgroundCopyJob* job, const base::string16& remote_name) const { - std::vector<ScopedComPtr<IBackgroundCopyFile> > files; + std::vector<ScopedComPtr<IBackgroundCopyFile>> files; HRESULT hr = GetFilesInJob(job, &files); if (FAILED(hr)) return false; @@ -344,7 +344,7 @@ } void CleanupJobFiles(IBackgroundCopyJob* job) { - std::vector<ScopedComPtr<IBackgroundCopyFile> > files; + std::vector<ScopedComPtr<IBackgroundCopyFile>> files; if (FAILED(GetFilesInJob(job, &files))) return; for (size_t i = 0; i != files.size(); ++i) { @@ -371,7 +371,7 @@ last_sweep = current_time; - std::vector<ScopedComPtr<IBackgroundCopyJob> > jobs; + std::vector<ScopedComPtr<IBackgroundCopyJob>> jobs; HRESULT hr = FindBitsJobIf( std::bind2nd(JobCreationOlderThanDays(), kPurgeStaleJobsAfterDays), bits_manager.get(), &jobs); @@ -418,10 +418,9 @@ void BackgroundDownloader::DoStartDownload(const GURL& url) { DCHECK(thread_checker_.CalledOnValidThread()); - task_runner_->PostTask( - FROM_HERE, - base::Bind( - &BackgroundDownloader::BeginDownload, base::Unretained(this), url)); + task_runner_->PostTask(FROM_HERE, + base::Bind(&BackgroundDownloader::BeginDownload, + base::Unretained(this), url)); } // Called once when this class is asked to do a download. Creates or opens @@ -444,10 +443,8 @@ // A repeating timer retains the user task. This timer can be stopped and // reset multiple times. timer_.reset(new base::RepeatingTimer<BackgroundDownloader>); - timer_->Start(FROM_HERE, - base::TimeDelta::FromSeconds(kJobPollingIntervalSec), - this, - &BackgroundDownloader::OnDownloading); + timer_->Start(FROM_HERE, base::TimeDelta::FromSeconds(kJobPollingIntervalSec), + this, &BackgroundDownloader::OnDownloading); } // Called any time the timer fires. @@ -558,10 +555,7 @@ main_task_runner_->PostTask( FROM_HERE, base::Bind(&BackgroundDownloader::OnDownloadComplete, - base::Unretained(this), - is_handled, - result, - download_metrics)); + base::Unretained(this), is_handled, result, download_metrics)); // Once the task is posted to the the main thread, this object may be deleted // by its owner. It is not safe to access members of this object on the @@ -629,10 +623,8 @@ result.total_bytes = total_bytes; main_task_runner_->PostTask( - FROM_HERE, - base::Bind(&BackgroundDownloader::OnDownloadProgress, - base::Unretained(this), - result)); + FROM_HERE, base::Bind(&BackgroundDownloader::OnDownloadProgress, + base::Unretained(this), result)); } // Called when the download was cancelled. Since the observer should have @@ -672,7 +664,7 @@ } HRESULT BackgroundDownloader::CreateOrOpenJob(const GURL& url) { - std::vector<ScopedComPtr<IBackgroundCopyJob> > jobs; + std::vector<ScopedComPtr<IBackgroundCopyJob>> jobs; HRESULT hr = FindBitsJobIf( std::bind2nd(JobFileUrlEqual(), base::SysUTF8ToWide(url.spec())), bits_manager_.get(), &jobs); @@ -685,8 +677,8 @@ // display name is initialized later on. GUID guid = {0}; ScopedComPtr<IBackgroundCopyJob> job; - hr = bits_manager_->CreateJob( - kJobDescription, BG_JOB_TYPE_DOWNLOAD, &guid, job.Receive()); + hr = bits_manager_->CreateJob(kJobDescription, BG_JOB_TYPE_DOWNLOAD, &guid, + job.Receive()); if (FAILED(hr)) return hr; @@ -742,7 +734,7 @@ if (FAILED(hr) && hr != BG_S_UNABLE_TO_DELETE_FILES) return hr; - std::vector<ScopedComPtr<IBackgroundCopyFile> > files; + std::vector<ScopedComPtr<IBackgroundCopyFile>> files; hr = GetFilesInJob(job_.get(), &files); if (FAILED(hr)) return hr; @@ -767,4 +759,4 @@ return S_OK; } -} // namespace component_updater +} // namespace update_client
diff --git a/components/component_updater/background_downloader_win.h b/components/update_client/background_downloader_win.h similarity index 90% rename from components/component_updater/background_downloader_win.h rename to components/update_client/background_downloader_win.h index fe4a919a..48ce6dd 100644 --- a/components/component_updater/background_downloader_win.h +++ b/components/update_client/background_downloader_win.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 COMPONENTS_COMPONENT_UPDATER_BACKGROUND_DOWNLOADER_WIN_H_ -#define COMPONENTS_COMPONENT_UPDATER_BACKGROUND_DOWNLOADER_WIN_H_ +#ifndef COMPONENTS_UPDATE_CLIENT_BACKGROUND_DOWNLOADER_WIN_H_ +#define COMPONENTS_UPDATE_CLIENT_BACKGROUND_DOWNLOADER_WIN_H_ #include <windows.h> #include <bits.h> @@ -15,7 +15,7 @@ #include "base/time/time.h" #include "base/timer/timer.h" #include "base/win/scoped_comptr.h" -#include "components/component_updater/crx_downloader.h" +#include "components/update_client/crx_downloader.h" namespace base { class FilePath; @@ -23,7 +23,7 @@ class SingleThreadTaskRunner; } -namespace component_updater { +namespace update_client { // Implements a downloader in terms of the BITS service. The public interface // of this class and the CrxDownloader overrides are expected to be called @@ -94,7 +94,7 @@ // The timer and the BITS interface pointers have thread affinity. These // members are initialized on the task runner and they must be destroyed // on the task runner. - scoped_ptr<base::RepeatingTimer<BackgroundDownloader> > timer_; + scoped_ptr<base::RepeatingTimer<BackgroundDownloader>> timer_; base::win::ScopedComPtr<IBackgroundCopyManager> bits_manager_; base::win::ScopedComPtr<IBackgroundCopyJob> job_; @@ -114,6 +114,6 @@ DISALLOW_COPY_AND_ASSIGN(BackgroundDownloader); }; -} // namespace component_updater +} // namespace update_client -#endif // COMPONENTS_COMPONENT_UPDATER_BACKGROUND_DOWNLOADER_WIN_H_ +#endif // COMPONENTS_UPDATE_CLIENT_BACKGROUND_DOWNLOADER_WIN_H_
diff --git a/components/component_updater/component_patcher.cc b/components/update_client/component_patcher.cc similarity index 89% rename from components/component_updater/component_patcher.cc rename to components/update_client/component_patcher.cc index 17c997f1..651756e 100644 --- a/components/component_updater/component_patcher.cc +++ b/components/update_client/component_patcher.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 "components/component_updater/component_patcher.h" +#include "components/update_client/component_patcher.h" #include <string> #include <vector> @@ -15,10 +15,9 @@ #include "base/location.h" #include "base/memory/weak_ptr.h" #include "base/values.h" -#include "components/component_updater/component_patcher_operation.h" -#include "components/component_updater/component_updater_service.h" +#include "components/update_client/component_patcher_operation.h" -namespace component_updater { +namespace update_client { namespace { @@ -95,10 +94,7 @@ DonePatching(ComponentUnpacker::kDeltaUnsupportedCommand, 0); return; } - current_operation_->Run(command_args, - input_dir_, - unpack_dir_, - installer_, + current_operation_->Run(command_args, input_dir_, unpack_dir_, installer_, base::Bind(&ComponentPatcher::DonePatchingFile, scoped_refptr<ComponentPatcher>(this)), task_runner_); @@ -122,4 +118,4 @@ callback_.Reset(); } -} // namespace component_updater +} // namespace update_client
diff --git a/components/component_updater/component_patcher.h b/components/update_client/component_patcher.h similarity index 92% rename from components/component_updater/component_patcher.h rename to components/update_client/component_patcher.h index c83971cc..b7dd216d 100644 --- a/components/component_updater/component_patcher.h +++ b/components/update_client/component_patcher.h
@@ -24,21 +24,21 @@ // fingerprint of the installed files, to later identify the existing files to // the server so that a proper differential update can be provided next cycle. -#ifndef COMPONENTS_COMPONENT_UPDATER_COMPONENT_PATCHER_H_ -#define COMPONENTS_COMPONENT_UPDATER_COMPONENT_PATCHER_H_ +#ifndef COMPONENTS_UPDATE_CLIENT_COMPONENT_PATCHER_H_ +#define COMPONENTS_UPDATE_CLIENT_COMPONENT_PATCHER_H_ #include "base/callback_forward.h" #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/values.h" -#include "components/component_updater/component_unpacker.h" +#include "components/update_client/component_unpacker.h" namespace base { class FilePath; } -namespace component_updater { +namespace update_client { class ComponentInstaller; class DeltaUpdateOp; @@ -97,6 +97,6 @@ DISALLOW_COPY_AND_ASSIGN(ComponentPatcher); }; -} // namespace component_updater +} // namespace update_client -#endif // COMPONENTS_COMPONENT_UPDATER_COMPONENT_PATCHER_H_ +#endif // COMPONENTS_UPDATE_CLIENT_COMPONENT_PATCHER_H_
diff --git a/components/component_updater/component_patcher_operation.cc b/components/update_client/component_patcher_operation.cc similarity index 91% rename from components/component_updater/component_patcher_operation.cc rename to components/update_client/component_patcher_operation.cc index fdc5e0d..adb5b8f 100644 --- a/components/component_updater/component_patcher_operation.cc +++ b/components/update_client/component_patcher_operation.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 "components/component_updater/component_patcher_operation.h" +#include "components/update_client/component_patcher_operation.h" #include <stdint.h> #include <vector> @@ -12,8 +12,8 @@ #include "base/files/memory_mapped_file.h" #include "base/location.h" #include "base/strings/string_number_conversions.h" -#include "components/component_updater/component_patcher.h" -#include "components/component_updater/component_updater_service.h" +#include "components/update_client/component_patcher.h" +#include "components/update_client/update_client.h" #include "courgette/courgette.h" #include "courgette/third_party/bsdiff.h" #include "crypto/secure_hash.h" @@ -22,7 +22,7 @@ using crypto::SecureHash; -namespace component_updater { +namespace update_client { namespace { @@ -217,10 +217,7 @@ void DeltaUpdateOpPatch::DoRun(const ComponentUnpacker::Callback& callback) { if (out_of_process_patcher_.get()) { out_of_process_patcher_->Patch( - operation_, - GetTaskRunner(), - input_abs_path_, - patch_abs_path_, + operation_, GetTaskRunner(), input_abs_path_, patch_abs_path_, output_abs_path_, base::Bind(&DeltaUpdateOpPatch::DonePatching, this, callback)); return; @@ -228,14 +225,13 @@ if (operation_ == kBsdiff) { DonePatching(callback, - courgette::ApplyBinaryPatch( - input_abs_path_, patch_abs_path_, output_abs_path_)); + courgette::ApplyBinaryPatch(input_abs_path_, patch_abs_path_, + output_abs_path_)); } else if (operation_ == kCourgette) { - DonePatching( - callback, - courgette::ApplyEnsemblePatch(input_abs_path_.value().c_str(), - patch_abs_path_.value().c_str(), - output_abs_path_.value().c_str())); + DonePatching(callback, courgette::ApplyEnsemblePatch( + input_abs_path_.value().c_str(), + patch_abs_path_.value().c_str(), + output_abs_path_.value().c_str())); } else { NOTREACHED(); } @@ -263,4 +259,4 @@ } } -} // namespace component_updater +} // namespace update_client
diff --git a/components/component_updater/component_patcher_operation.h b/components/update_client/component_patcher_operation.h similarity index 94% rename from components/component_updater/component_patcher_operation.h rename to components/update_client/component_patcher_operation.h index 2bf1ab6..8f31c043 100644 --- a/components/component_updater/component_patcher_operation.h +++ b/components/update_client/component_patcher_operation.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 COMPONENTS_COMPONENT_UPDATER_COMPONENT_PATCHER_OPERATION_H_ -#define COMPONENTS_COMPONENT_UPDATER_COMPONENT_PATCHER_OPERATION_H_ +#ifndef COMPONENTS_UPDATE_CLIENT_COMPONENT_PATCHER_OPERATION_H_ +#define COMPONENTS_UPDATE_CLIENT_COMPONENT_PATCHER_OPERATION_H_ #include <string> @@ -12,13 +12,13 @@ #include "base/files/file_path.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "components/component_updater/component_unpacker.h" +#include "components/update_client/component_unpacker.h" namespace base { class DictionaryValue; } // namespace base -namespace component_updater { +namespace update_client { extern const char kOp[]; extern const char kBsdiff[]; @@ -179,6 +179,6 @@ const std::string& operation, scoped_refptr<OutOfProcessPatcher> out_of_process_patcher); -} // namespace component_updater +} // namespace update_client -#endif // COMPONENTS_COMPONENT_UPDATER_COMPONENT_PATCHER_OPERATION_H_ +#endif // COMPONENTS_UPDATE_CLIENT_COMPONENT_PATCHER_OPERATION_H_
diff --git a/components/component_updater/component_unpacker.cc b/components/update_client/component_unpacker.cc similarity index 82% rename from components/component_updater/component_unpacker.cc rename to components/update_client/component_unpacker.cc index d904e326..27d75b9 100644 --- a/components/component_updater/component_unpacker.cc +++ b/components/update_client/component_unpacker.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 "components/component_updater/component_unpacker.h" +#include "components/update_client/component_unpacker.h" #include <stdint.h> #include <string> @@ -19,18 +19,18 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" #include "base/values.h" -#include "components/component_updater/component_patcher.h" -#include "components/component_updater/component_patcher_operation.h" -#include "components/component_updater/component_updater_service.h" #include "components/crx_file/constants.h" #include "components/crx_file/crx_file.h" +#include "components/update_client/component_patcher.h" +#include "components/update_client/component_patcher_operation.h" +#include "components/update_client/update_client.h" #include "crypto/secure_hash.h" #include "crypto/signature_verifier.h" #include "third_party/zlib/google/zip.h" using crypto::SecureHash; -namespace component_updater { +namespace update_client { namespace { @@ -45,8 +45,7 @@ return; crx_file::CrxFile::Error error; - scoped_ptr<crx_file::CrxFile> crx( - crx_file::CrxFile::Parse(header, &error)); + scoped_ptr<crx_file::CrxFile> crx(crx_file::CrxFile::Parse(header, &error)); if (!crx.get()) return; is_delta_ = crx_file::CrxFile::HeaderIsDelta(header); @@ -63,13 +62,11 @@ return; crypto::SignatureVerifier verifier; - if (!verifier.VerifyInit(crx_file::kSignatureAlgorithm, - base::checked_cast<int>( - sizeof(crx_file::kSignatureAlgorithm)), - &signature[0], - base::checked_cast<int>(signature.size()), - &key[0], - base::checked_cast<int>(key.size()))) { + if (!verifier.VerifyInit( + crx_file::kSignatureAlgorithm, + base::checked_cast<int>(sizeof(crx_file::kSignatureAlgorithm)), + &signature[0], base::checked_cast<int>(signature.size()), &key[0], + base::checked_cast<int>(key.size()))) { // Signature verification initialization failed. This is most likely // caused by a public key in the wrong format (should encode algorithm). return; @@ -106,14 +103,14 @@ const base::FilePath& path, const std::string& fingerprint, ComponentInstaller* installer, - scoped_refptr<OutOfProcessPatcher> out_of_process_patcher, + scoped_refptr<OutOfProcessPatcher> oop_patcher, scoped_refptr<base::SequencedTaskRunner> task_runner) : pk_hash_(pk_hash), path_(path), is_delta_(false), fingerprint_(fingerprint), installer_(installer), - out_of_process_patcher_(out_of_process_patcher), + oop_patcher_(oop_patcher), error_(kNone), extended_error_(0), task_runner_(task_runner) { @@ -213,23 +210,18 @@ error_ = kUnzipPathError; return false; } - patcher_ = new ComponentPatcher(unpack_diff_path_, - unpack_path_, - installer_, - out_of_process_patcher_, - task_runner_); + patcher_ = new ComponentPatcher(unpack_diff_path_, unpack_path_, installer_, + oop_patcher_, task_runner_); task_runner_->PostTask( FROM_HERE, - base::Bind(&ComponentPatcher::Start, - patcher_, + base::Bind(&ComponentPatcher::Start, patcher_, base::Bind(&ComponentUnpacker::EndPatching, scoped_refptr<ComponentUnpacker>(this)))); } else { - task_runner_->PostTask(FROM_HERE, - base::Bind(&ComponentUnpacker::EndPatching, - scoped_refptr<ComponentUnpacker>(this), - kNone, - 0)); + task_runner_->PostTask( + FROM_HERE, + base::Bind(&ComponentUnpacker::EndPatching, + scoped_refptr<ComponentUnpacker>(this), kNone, 0)); } return true; } @@ -257,8 +249,7 @@ if (static_cast<int>(fingerprint_.size()) != base::WriteFile( unpack_path_.Append(FILE_PATH_LITERAL("manifest.fingerprint")), - fingerprint_.c_str(), - base::checked_cast<int>(fingerprint_.size()))) { + fingerprint_.c_str(), base::checked_cast<int>(fingerprint_.size()))) { error_ = kFingerprintWriteFailed; return; } @@ -285,4 +276,4 @@ ComponentUnpacker::~ComponentUnpacker() { } -} // namespace component_updater +} // namespace update_client
diff --git a/components/component_updater/component_unpacker.h b/components/update_client/component_unpacker.h similarity index 92% rename from components/component_updater/component_unpacker.h rename to components/update_client/component_unpacker.h index 97d57dc..7c2b6efc 100644 --- a/components/component_updater/component_unpacker.h +++ b/components/update_client/component_unpacker.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 COMPONENTS_COMPONENT_UPDATER_COMPONENT_UNPACKER_H_ -#define COMPONENTS_COMPONENT_UPDATER_COMPONENT_UNPACKER_H_ +#ifndef COMPONENTS_UPDATE_CLIENT_COMPONENT_UNPACKER_H_ +#define COMPONENTS_UPDATE_CLIENT_COMPONENT_UNPACKER_H_ #include <stdint.h> #include <string> @@ -17,7 +17,7 @@ #include "base/memory/scoped_ptr.h" #include "base/sequenced_task_runner.h" -namespace component_updater { +namespace update_client { class ComponentInstaller; class ComponentPatcher; @@ -99,7 +99,7 @@ const base::FilePath& path, const std::string& fingerprint, ComponentInstaller* installer, - scoped_refptr<OutOfProcessPatcher> out_of_process_patcher, + scoped_refptr<OutOfProcessPatcher> oop_patcher, scoped_refptr<base::SequencedTaskRunner> task_runner); // Begins the actual unpacking of the files. May invoke a patcher if the @@ -149,7 +149,7 @@ scoped_refptr<ComponentPatcher> patcher_; ComponentInstaller* installer_; Callback callback_; - scoped_refptr<OutOfProcessPatcher> out_of_process_patcher_; + scoped_refptr<OutOfProcessPatcher> oop_patcher_; Error error_; int extended_error_; scoped_refptr<base::SequencedTaskRunner> task_runner_; @@ -157,6 +157,6 @@ DISALLOW_COPY_AND_ASSIGN(ComponentUnpacker); }; -} // namespace component_updater +} // namespace update_client -#endif // COMPONENTS_COMPONENT_UPDATER_COMPONENT_UNPACKER_H_ +#endif // COMPONENTS_UPDATE_CLIENT_COMPONENT_UNPACKER_H_
diff --git a/components/component_updater/component_updater_configurator.h b/components/update_client/configurator.h similarity index 86% rename from components/component_updater/component_updater_configurator.h rename to components/update_client/configurator.h index 1eea184..b9a86fae 100644 --- a/components/component_updater/component_updater_configurator.h +++ b/components/update_client/configurator.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 COMPONENTS_COMPONENT_UPDATER_COMPONENT_UPDATER_CONFIGURATOR_H_ -#define COMPONENTS_COMPONENT_UPDATER_COMPONENT_UPDATER_CONFIGURATOR_H_ +#ifndef COMPONENTS_UPDATE_CLIENT_CONFIGURATOR_H_ +#define COMPONENTS_UPDATE_CLIENT_CONFIGURATOR_H_ #include <string> #include <vector> @@ -23,11 +23,14 @@ class URLRequestContextGetter; } -namespace component_updater { +namespace update_client { class OutOfProcessPatcher; // Controls the component updater behavior. +// TODO(sorin): this class will be split soon in two. One class controls +// the behavior of the update client, and the other class controls the +// behavior of the component updater. class Configurator { public: virtual ~Configurator() {} @@ -90,8 +93,8 @@ // Returns a new out of process patcher. May be NULL for implementations // that patch in-process. - virtual scoped_refptr<OutOfProcessPatcher> CreateOutOfProcessPatcher() - const = 0; + virtual scoped_refptr<update_client::OutOfProcessPatcher> + CreateOutOfProcessPatcher() const = 0; // True means that this client can handle delta updates. virtual bool DeltasEnabled() const = 0; @@ -108,9 +111,9 @@ // This thread must be capable of IO. On Windows, this thread must be // initialized for use of COM objects. virtual scoped_refptr<base::SingleThreadTaskRunner> - GetSingleThreadTaskRunner() const = 0; + GetSingleThreadTaskRunner() const = 0; }; -} // namespace component_updater +} // namespace update_client -#endif // COMPONENTS_COMPONENT_UPDATER_COMPONENT_UPDATER_CONFIGURATOR_H_ +#endif // COMPONENTS_UPDATE_CLIENT_CONFIGURATOR_H_
diff --git a/components/component_updater/crx_downloader.cc b/components/update_client/crx_downloader.cc similarity index 88% rename from components/component_updater/crx_downloader.cc rename to components/update_client/crx_downloader.cc index b56b397..ecbf301 100644 --- a/components/component_updater/crx_downloader.cc +++ b/components/update_client/crx_downloader.cc
@@ -2,18 +2,18 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/component_updater/crx_downloader.h" +#include "components/update_client/crx_downloader.h" #include "base/logging.h" #include "base/sequenced_task_runner.h" #include "base/single_thread_task_runner.h" -#include "components/component_updater/url_fetcher_downloader.h" +#include "components/update_client/url_fetcher_downloader.h" #if defined(OS_WIN) -#include "components/component_updater/background_downloader_win.h" +#include "components/update_client/background_downloader_win.h" #endif -namespace component_updater { +namespace update_client { CrxDownloader::Result::Result() : error(0), downloaded_bytes(-1), total_bytes(-1) { @@ -36,12 +36,11 @@ scoped_refptr<base::SingleThreadTaskRunner> background_task_runner) { scoped_ptr<CrxDownloader> url_fetcher_downloader( new UrlFetcherDownloader(scoped_ptr<CrxDownloader>().Pass(), - context_getter, - url_fetcher_task_runner)); + context_getter, url_fetcher_task_runner)); #if defined(OS_WIN) if (is_background_download) { - return new BackgroundDownloader( - url_fetcher_downloader.Pass(), context_getter, background_task_runner); + return new BackgroundDownloader(url_fetcher_downloader.Pass(), + context_getter, background_task_runner); } #endif @@ -70,8 +69,8 @@ return download_metrics_; std::vector<DownloadMetrics> retval(successor_->download_metrics()); - retval.insert( - retval.begin(), download_metrics_.begin(), download_metrics_.end()); + retval.insert(retval.begin(), download_metrics_.begin(), + download_metrics_.end()); return retval; } @@ -155,4 +154,4 @@ progress_callback_.Run(result); } -} // namespace component_updater +} // namespace update_client
diff --git a/components/component_updater/crx_downloader.h b/components/update_client/crx_downloader.h similarity index 95% rename from components/component_updater/crx_downloader.h rename to components/update_client/crx_downloader.h index 4a421f2..661b5c8 100644 --- a/components/component_updater/crx_downloader.h +++ b/components/update_client/crx_downloader.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 COMPONENTS_COMPONENT_UPDATER_CRX_DOWNLOADER_H_ -#define COMPONENTS_COMPONENT_UPDATER_CRX_DOWNLOADER_H_ +#ifndef COMPONENTS_UPDATE_CLIENT_CRX_DOWNLOADER_H_ +#define COMPONENTS_UPDATE_CLIENT_CRX_DOWNLOADER_H_ #include <stdint.h> #include <vector> @@ -25,7 +25,7 @@ class URLRequestContextGetter; } -namespace component_updater { +namespace update_client { // Defines a download interface for downloading components, with retrying on // fallback urls in case of errors. This class implements a chain of @@ -151,6 +151,6 @@ DISALLOW_COPY_AND_ASSIGN(CrxDownloader); }; -} // namespace component_updater +} // namespace update_client -#endif // COMPONENTS_COMPONENT_UPDATER_CRX_DOWNLOADER_H_ +#endif // COMPONENTS_UPDATE_CLIENT_CRX_DOWNLOADER_H_
diff --git a/components/component_updater/crx_update_item.h b/components/update_client/crx_update_item.h similarity index 92% rename from components/component_updater/crx_update_item.h rename to components/update_client/crx_update_item.h index 8a64146..ba38a1b 100644 --- a/components/component_updater/crx_update_item.h +++ b/components/update_client/crx_update_item.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 COMPONENTS_COMPONENT_UPDATER_CRX_UPDATE_ITEM_H_ -#define COMPONENTS_COMPONENT_UPDATER_CRX_UPDATE_ITEM_H_ +#ifndef COMPONENTS_UPDATE_CLIENT_CRX_UPDATE_ITEM_H_ +#define COMPONENTS_UPDATE_CLIENT_CRX_UPDATE_ITEM_H_ #include <string> #include <vector> @@ -11,10 +11,10 @@ #include "base/memory/weak_ptr.h" #include "base/time/time.h" #include "base/version.h" -#include "components/component_updater/component_updater_service.h" -#include "components/component_updater/crx_downloader.h" +#include "components/update_client/crx_downloader.h" +#include "components/update_client/update_client.h" -namespace component_updater { +namespace update_client { // This is the one and only per-item state structure. Designed to be hosted // in a std::vector or a std::list. The two main members are |component| @@ -124,6 +124,6 @@ }; }; -} // namespace component_updater +} // namespace update_client -#endif // COMPONENTS_COMPONENT_UPDATER_CRX_UPDATE_ITEM_H_ +#endif // COMPONENTS_UPDATE_CLIENT_CRX_UPDATE_ITEM_H_
diff --git a/components/component_updater/component_updater_ping_manager.cc b/components/update_client/ping_manager.cc similarity index 83% rename from components/component_updater/component_updater_ping_manager.cc rename to components/update_client/ping_manager.cc index 8bfd5ed..d3eb83c 100644 --- a/components/component_updater/component_updater_ping_manager.cc +++ b/components/update_client/ping_manager.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 "components/component_updater/component_updater_ping_manager.h" +#include "components/update_client/ping_manager.h" #include <string> #include <vector> @@ -19,17 +19,14 @@ #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/threading/thread_checker.h" -#include "components/component_updater/component_updater_configurator.h" -#include "components/component_updater/component_updater_utils.h" -#include "components/component_updater/crx_update_item.h" -#include "components/component_updater/request_sender.h" +#include "components/update_client/configurator.h" +#include "components/update_client/crx_update_item.h" +#include "components/update_client/request_sender.h" +#include "components/update_client/utils.h" +#include "net/url_request/url_fetcher.h" #include "url/gurl.h" -namespace net { -class URLFetcher; -} // namespace net - -namespace component_updater { +namespace update_client { namespace { @@ -54,8 +51,7 @@ const CrxDownloader::DownloadMetrics& metrics = item->download_metrics[i]; std::string event("<event eventtype=\"14\""); StringAppendF(&event, " eventresult=\"%d\"", metrics.error == 0); - StringAppendF(&event, - " downloader=\"%s\"", + StringAppendF(&event, " downloader=\"%s\"", DownloaderToString(metrics.downloader)); if (metrics.error) { StringAppendF(&event, " errorcode=\"%d\"", metrics.error); @@ -64,19 +60,16 @@ // -1 means that the byte counts are not known. if (metrics.downloaded_bytes != -1) { - StringAppendF(&event, - " downloaded=\"%s\"", + StringAppendF(&event, " downloaded=\"%s\"", base::Int64ToString(metrics.downloaded_bytes).c_str()); } if (metrics.total_bytes != -1) { - StringAppendF(&event, - " total=\"%s\"", + StringAppendF(&event, " total=\"%s\"", base::Int64ToString(metrics.total_bytes).c_str()); } if (metrics.download_time_ms) { - StringAppendF(&event, - " download_time_ms=\"%s\"", + StringAppendF(&event, " download_time_ms=\"%s\"", base::Uint64ToString(metrics.download_time_ms).c_str()); } StringAppendF(&event, "/>"); @@ -105,14 +98,14 @@ if (HasDiffUpdate(item)) StringAppendF(&ping_event, " diffresult=\"%d\"", !item->diff_update_failed); if (item->diff_error_category) { - StringAppendF( - &ping_event, " differrorcat=\"%d\"", item->diff_error_category); + StringAppendF(&ping_event, " differrorcat=\"%d\"", + item->diff_error_category); } if (item->diff_error_code) StringAppendF(&ping_event, " differrorcode=\"%d\"", item->diff_error_code); if (item->diff_extra_code1) { - StringAppendF( - &ping_event, " diffextracode1=\"%d\"", item->diff_extra_code1); + StringAppendF(&ping_event, " diffextracode1=\"%d\"", + item->diff_extra_code1); } if (!item->previous_fp.empty()) StringAppendF(&ping_event, " previousfp=\"%s\"", item->previous_fp.c_str()); @@ -138,11 +131,8 @@ BuildDownloadCompleteEventElements(item).c_str())); // download events return BuildProtocolRequest(config.GetBrowserVersion().GetString(), - config.GetChannel(), - config.GetLang(), - config.GetOSLongName(), - app_element, - ""); + config.GetChannel(), config.GetLang(), + config.GetOSLongName(), app_element, ""); } // Sends a fire and forget ping. The instances of this class have no @@ -188,8 +178,7 @@ request_sender_.reset(new RequestSender(config_)); request_sender_->Send( - BuildPing(config_, item), - urls, + BuildPing(config_, item), urls, base::Bind(&PingSender::OnRequestSenderComplete, base::Unretained(this))); return true; } @@ -210,4 +199,4 @@ delete ping_sender; } -} // namespace component_updater +} // namespace update_client
diff --git a/components/component_updater/component_updater_ping_manager.h b/components/update_client/ping_manager.h similarity index 68% rename from components/component_updater/component_updater_ping_manager.h rename to components/update_client/ping_manager.h index e48ae05..df2fa44 100644 --- a/components/component_updater/component_updater_ping_manager.h +++ b/components/update_client/ping_manager.h
@@ -2,12 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_COMPONENT_UPDATER_COMPONENT_UPDATER_PING_MANAGER_H_ -#define COMPONENTS_COMPONENT_UPDATER_COMPONENT_UPDATER_PING_MANAGER_H_ +#ifndef COMPONENTS_UPDATE_CLIENT_PING_MANAGER_H_ +#define COMPONENTS_UPDATE_CLIENT_PING_MANAGER_H_ #include "base/macros.h" -namespace component_updater { +namespace update_client { class Configurator; struct CrxUpdateItem; @@ -27,6 +27,6 @@ DISALLOW_COPY_AND_ASSIGN(PingManager); }; -} // namespace component_updater +} // namespace update_client -#endif // COMPONENTS_COMPONENT_UPDATER_COMPONENT_UPDATER_PING_MANAGER_H_ +#endif // COMPONENTS_UPDATE_CLIENT_PING_MANAGER_H_
diff --git a/components/component_updater/request_sender.cc b/components/update_client/request_sender.cc similarity index 81% rename from components/component_updater/request_sender.cc rename to components/update_client/request_sender.cc index da6f794..726c2fa 100644 --- a/components/component_updater/request_sender.cc +++ b/components/update_client/request_sender.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 "components/component_updater/request_sender.h" +#include "components/update_client/request_sender.h" #include "base/bind.h" #include "base/bind_helpers.h" @@ -10,11 +10,11 @@ #include "base/logging.h" #include "base/single_thread_task_runner.h" #include "base/thread_task_runner_handle.h" -#include "components/component_updater/component_updater_configurator.h" -#include "components/component_updater/component_updater_utils.h" +#include "components/update_client/configurator.h" +#include "components/update_client/utils.h" #include "net/url_request/url_fetcher.h" -namespace component_updater { +namespace update_client { RequestSender::RequestSender(const Configurator& config) : config_(config) { } @@ -46,8 +46,8 @@ DCHECK(cur_url_->is_valid()); DCHECK(thread_checker_.CalledOnValidThread()); - url_fetcher_.reset(SendProtocolRequest( - *cur_url_, request_string_, this, config_.RequestContext())); + url_fetcher_.reset(SendProtocolRequest(*cur_url_, request_string_, this, + config_.RequestContext())); } void RequestSender::OnURLFetchComplete(const net::URLFetcher* source) { @@ -67,4 +67,4 @@ request_sender_callback_.Run(source); } -} // namespace component_updater +} // namespace update_client
diff --git a/components/component_updater/request_sender.h b/components/update_client/request_sender.h similarity index 87% rename from components/component_updater/request_sender.h rename to components/update_client/request_sender.h index 5d137e2..5c05350d 100644 --- a/components/component_updater/request_sender.h +++ b/components/update_client/request_sender.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 COMPONENTS_COMPONENT_UPDATER_REQUEST_SENDER_H_ -#define COMPONENTS_COMPONENT_UPDATER_REQUEST_SENDER_H_ +#ifndef COMPONENTS_UPDATE_CLIENT_REQUEST_SENDER_H_ +#define COMPONENTS_UPDATE_CLIENT_REQUEST_SENDER_H_ #include <string> #include <vector> @@ -20,7 +20,7 @@ class URLFetcher; } -namespace component_updater { +namespace update_client { class Configurator; @@ -59,6 +59,6 @@ DISALLOW_COPY_AND_ASSIGN(RequestSender); }; -} // namespace component_updater +} // namespace update_client -#endif // COMPONENTS_COMPONENT_UPDATER_REQUEST_SENDER_H_ +#endif // COMPONENTS_UPDATE_CLIENT_REQUEST_SENDER_H_
diff --git a/components/component_updater/test/DEPS b/components/update_client/test/DEPS similarity index 100% rename from components/component_updater/test/DEPS rename to components/update_client/test/DEPS
diff --git a/components/component_updater/test/component_patcher_unittest.cc b/components/update_client/test/component_patcher_unittest.cc similarity index 85% rename from components/component_updater/test/component_patcher_unittest.cc rename to components/update_client/test/component_patcher_unittest.cc index 2b980bd..ce6e7a1 100644 --- a/components/component_updater/test/component_patcher_unittest.cc +++ b/components/update_client/test/component_patcher_unittest.cc
@@ -13,11 +13,10 @@ #include "base/path_service.h" #include "base/run_loop.h" #include "base/values.h" -#include "components/component_updater/component_patcher.h" -#include "components/component_updater/component_patcher_operation.h" -#include "components/component_updater/component_updater_service.h" -#include "components/component_updater/test/component_patcher_unittest.h" -#include "components/component_updater/test/test_installer.h" +#include "components/update_client/component_patcher.h" +#include "components/update_client/component_patcher_operation.h" +#include "components/update_client/test/component_patcher_unittest.h" +#include "components/update_client/test/test_installer.h" #include "courgette/courgette.h" #include "courgette/third_party/bsdiff.h" #include "testing/gtest/include/gtest/gtest.h" @@ -28,7 +27,7 @@ public: TestCallback(); virtual ~TestCallback() {} - void Set(component_updater::ComponentUnpacker::Error error, int extra_code); + void Set(update_client::ComponentUnpacker::Error error, int extra_code); int error_; int extra_code_; @@ -41,7 +40,7 @@ TestCallback::TestCallback() : error_(-1), extra_code_(-1), called_(false) { } -void TestCallback::Set(component_updater::ComponentUnpacker::Error error, +void TestCallback::Set(update_client::ComponentUnpacker::Error error, int extra_code) { error_ = error; extra_code_ = extra_code; @@ -50,15 +49,18 @@ } // namespace -namespace component_updater { +namespace update_client { namespace { base::FilePath test_file(const char* file) { base::FilePath path; PathService::Get(base::DIR_SOURCE_ROOT, &path); - return path.AppendASCII("components").AppendASCII("test").AppendASCII("data") - .AppendASCII("component_updater").AppendASCII(file); + return path.AppendASCII("components") + .AppendASCII("test") + .AppendASCII("data") + .AppendASCII("update_client") + .AppendASCII(file); } } // namespace @@ -88,10 +90,7 @@ TestCallback callback; scoped_refptr<DeltaUpdateOp> op = new DeltaUpdateOpCreate(); - op->Run(command_args.get(), - input_dir_.path(), - unpack_dir_.path(), - NULL, + op->Run(command_args.get(), input_dir_.path(), unpack_dir_.path(), NULL, base::Bind(&TestCallback::Set, base::Unretained(&callback)), task_runner_); base::RunLoop().RunUntilIdle(); @@ -118,9 +117,7 @@ TestCallback callback; scoped_refptr<DeltaUpdateOp> op = new DeltaUpdateOpCopy(); - op->Run(command_args.get(), - input_dir_.path(), - unpack_dir_.path(), + op->Run(command_args.get(), input_dir_.path(), unpack_dir_.path(), installer_.get(), base::Bind(&TestCallback::Set, base::Unretained(&callback)), task_runner_); @@ -153,9 +150,7 @@ TestCallback callback; scoped_refptr<DeltaUpdateOp> op = CreateDeltaUpdateOp("courgette", NULL /* out_of_process_patcher */); - op->Run(command_args.get(), - input_dir_.path(), - unpack_dir_.path(), + op->Run(command_args.get(), input_dir_.path(), unpack_dir_.path(), installer_.get(), base::Bind(&TestCallback::Set, base::Unretained(&callback)), task_runner_); @@ -188,9 +183,7 @@ TestCallback callback; scoped_refptr<DeltaUpdateOp> op = CreateDeltaUpdateOp("bsdiff", NULL /* out_of_process_patcher */); - op->Run(command_args.get(), - input_dir_.path(), - unpack_dir_.path(), + op->Run(command_args.get(), input_dir_.path(), unpack_dir_.path(), installer_.get(), base::Bind(&TestCallback::Set, base::Unretained(&callback)), task_runner_); @@ -204,4 +197,4 @@ test_file("binary_output.bin"))); } -} // namespace component_updater +} // namespace update_client
diff --git a/components/component_updater/test/component_patcher_unittest.h b/components/update_client/test/component_patcher_unittest.h similarity index 75% rename from components/component_updater/test/component_patcher_unittest.h rename to components/update_client/test/component_patcher_unittest.h index 3eb1b97..f7a4aea 100644 --- a/components/component_updater/test/component_patcher_unittest.h +++ b/components/update_client/test/component_patcher_unittest.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 COMPONENTS_COMPONENT_UPDATER_TEST_COMPONENT_PATCHER_UNITTEST_H_ -#define COMPONENTS_COMPONENT_UPDATER_TEST_COMPONENT_PATCHER_UNITTEST_H_ +#ifndef COMPONENTS_UPDATE_CLIENT_TEST_COMPONENT_PATCHER_UNITTEST_H_ +#define COMPONENTS_UPDATE_CLIENT_TEST_COMPONENT_PATCHER_UNITTEST_H_ #include "base/files/file_path.h" #include "base/files/scoped_temp_dir.h" @@ -13,7 +13,7 @@ #include "courgette/third_party/bsdiff.h" #include "testing/gtest/include/gtest/gtest.h" -namespace component_updater { +namespace update_client { class MockComponentPatcher; class ReadOnlyTestInstaller; @@ -23,7 +23,7 @@ class ComponentPatcherOperationTest : public testing::Test { public: - explicit ComponentPatcherOperationTest(); + ComponentPatcherOperationTest(); ~ComponentPatcherOperationTest() override; protected: @@ -37,6 +37,6 @@ base::MessageLoopForIO loop_; }; -} // namespace component_updater +} // namespace update_client -#endif // COMPONENTS_COMPONENT_UPDATER_TEST_COMPONENT_PATCHER_UNITTEST_H_ +#endif // COMPONENTS_UPDATE_CLIENT_TEST_COMPONENT_PATCHER_UNITTEST_H_
diff --git a/components/component_updater/test/crx_downloader_unittest.cc b/components/update_client/test/crx_downloader_unittest.cc similarity index 95% rename from components/component_updater/test/crx_downloader_unittest.cc rename to components/update_client/test/crx_downloader_unittest.cc index ebc8d60..5b01b42 100644 --- a/components/component_updater/test/crx_downloader_unittest.cc +++ b/components/update_client/test/crx_downloader_unittest.cc
@@ -11,7 +11,7 @@ #include "base/message_loop/message_loop.h" #include "base/path_service.h" #include "base/run_loop.h" -#include "components/component_updater/crx_downloader.h" +#include "components/update_client/crx_downloader.h" #include "net/base/net_errors.h" #include "net/url_request/test_url_request_interceptor.h" #include "net/url_request/url_request_test_util.h" @@ -19,7 +19,7 @@ using base::ContentsEqual; -namespace component_updater { +namespace update_client { namespace { @@ -31,8 +31,11 @@ base::FilePath MakeTestFilePath(const char* file) { base::FilePath path; PathService::Get(base::DIR_SOURCE_ROOT, &path); - return path.AppendASCII("components").AppendASCII("test").AppendASCII("data") - .AppendASCII("component_updater").AppendASCII(file); + return path.AppendASCII("components") + .AppendASCII("test") + .AppendASCII("data") + .AppendASCII("update_client") + .AppendASCII(file); } } // namespace @@ -112,8 +115,7 @@ crx_downloader_.reset(CrxDownloader::Create( false, // Do not use the background downloader in these tests. - context_.get(), - base::MessageLoopProxy::current(), + context_.get(), base::MessageLoopProxy::current(), NULL)); // No |background_task_runner| because no background downloader. crx_downloader_->set_progress_callback(progress_callback_); @@ -249,8 +251,9 @@ get_interceptor_->SetResponse(expected_crx_url, test_file); crx_downloader_->StartDownloadFromUrl( - GURL("http://no.such.host" - "/download/jebgalgnebhfojomionfpkfelancnnkf.crx"), + GURL( + "http://no.such.host" + "/download/jebgalgnebhfojomionfpkfelancnnkf.crx"), callback_); RunThreads(); @@ -361,8 +364,9 @@ std::vector<GURL> urls; urls.push_back(GURL("http://localhost/no/such/file")); - urls.push_back(GURL("http://no.such.host/" - "/download/jebgalgnebhfojomionfpkfelancnnkf.crx")); + urls.push_back(GURL( + "http://no.such.host/" + "/download/jebgalgnebhfojomionfpkfelancnnkf.crx")); crx_downloader_->StartDownload(urls, callback_); RunThreads(); @@ -375,4 +379,4 @@ EXPECT_TRUE(download_complete_result_.response.empty()); } -} // namespace component_updater +} // namespace update_client
diff --git a/components/component_updater/test/component_updater_ping_manager_unittest.cc b/components/update_client/test/ping_manager_unittest.cc similarity index 94% rename from components/component_updater/test/component_updater_ping_manager_unittest.cc rename to components/update_client/test/ping_manager_unittest.cc index 48838749..95539f03 100644 --- a/components/component_updater/test/component_updater_ping_manager_unittest.cc +++ b/components/update_client/test/ping_manager_unittest.cc
@@ -6,16 +6,16 @@ #include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/version.h" -#include "components/component_updater/component_updater_ping_manager.h" -#include "components/component_updater/crx_update_item.h" -#include "components/component_updater/test/test_configurator.h" -#include "components/component_updater/test/url_request_post_interceptor.h" +#include "components/update_client/crx_update_item.h" +#include "components/update_client/ping_manager.h" +#include "components/update_client/test/test_configurator.h" +#include "components/update_client/test/url_request_post_interceptor.h" #include "net/url_request/url_request_test_util.h" #include "testing/gtest/include/gtest/gtest.h" using std::string; -namespace component_updater { +namespace update_client { class ComponentUpdaterPingManagerTest : public testing::Test { public: @@ -174,4 +174,4 @@ interceptor->Reset(); } -} // namespace component_updater +} // namespace update_client
diff --git a/components/component_updater/test/request_sender_unittest.cc b/components/update_client/test/request_sender_unittest.cc similarity index 93% rename from components/component_updater/test/request_sender_unittest.cc rename to components/update_client/test/request_sender_unittest.cc index 47e0e6f..f8ad042f 100644 --- a/components/component_updater/test/request_sender_unittest.cc +++ b/components/update_client/test/request_sender_unittest.cc
@@ -7,13 +7,13 @@ #include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h" -#include "components/component_updater/request_sender.h" -#include "components/component_updater/test/test_configurator.h" -#include "components/component_updater/test/url_request_post_interceptor.h" +#include "components/update_client/request_sender.h" +#include "components/update_client/test/test_configurator.h" +#include "components/update_client/test/url_request_post_interceptor.h" #include "net/url_request/url_fetcher.h" #include "testing/gtest/include/gtest/gtest.h" -namespace component_updater { +namespace update_client { namespace { @@ -128,8 +128,7 @@ urls.push_back(GURL(kUrl1)); urls.push_back(GURL(kUrl2)); request_sender_.reset(new RequestSender(*config_)); - request_sender_->Send("test", - urls, + request_sender_->Send("test", urls, base::Bind(&RequestSenderTest::RequestSenderComplete, base::Unretained(this))); RunThreads(); @@ -154,8 +153,7 @@ urls.push_back(GURL(kUrl1)); urls.push_back(GURL(kUrl2)); request_sender_.reset(new RequestSender(*config_)); - request_sender_->Send("test", - urls, + request_sender_->Send("test", urls, base::Bind(&RequestSenderTest::RequestSenderComplete, base::Unretained(this))); RunThreads(); @@ -184,8 +182,7 @@ urls.push_back(GURL(kUrl1)); urls.push_back(GURL(kUrl2)); request_sender_.reset(new RequestSender(*config_)); - request_sender_->Send("test", - urls, + request_sender_->Send("test", urls, base::Bind(&RequestSenderTest::RequestSenderComplete, base::Unretained(this))); RunThreads(); @@ -205,4 +202,4 @@ EXPECT_EQ(403, url_fetcher_source_->GetResponseCode()); } -} // namespace component_updater +} // namespace update_client
diff --git a/components/component_updater/test/test_configurator.cc b/components/update_client/test/test_configurator.cc similarity index 94% rename from components/component_updater/test/test_configurator.cc rename to components/update_client/test/test_configurator.cc index a1b88b3f..27aaf5f6 100644 --- a/components/component_updater/test/test_configurator.cc +++ b/components/update_client/test/test_configurator.cc
@@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/component_updater/test/test_configurator.h" +#include "components/update_client/test/test_configurator.h" #include "base/run_loop.h" #include "base/version.h" -#include "components/component_updater/component_patcher_operation.h" +#include "components/update_client/component_patcher_operation.h" #include "url/gurl.h" -namespace component_updater { +namespace update_client { namespace { @@ -151,4 +151,4 @@ return NULL; } -} // namespace component_updater +} // namespace update_client
diff --git a/components/component_updater/test/test_configurator.h b/components/update_client/test/test_configurator.h similarity index 61% rename from components/component_updater/test/test_configurator.h rename to components/update_client/test/test_configurator.h index 264b7c9..4943cca 100644 --- a/components/component_updater/test/test_configurator.h +++ b/components/update_client/test/test_configurator.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 COMPONENTS_COMPONENT_UPDATER_TEST_TEST_CONFIGURATOR_H_ -#define COMPONENTS_COMPONENT_UPDATER_TEST_TEST_CONFIGURATOR_H_ +#ifndef COMPONENTS_UPDATE_CLIENT_TEST_TEST_CONFIGURATOR_H_ +#define COMPONENTS_UPDATE_CLIENT_TEST_TEST_CONFIGURATOR_H_ #include <string> #include <utility> @@ -13,7 +13,7 @@ #include "base/compiler_specific.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "components/component_updater/component_updater_configurator.h" +#include "components/update_client/configurator.h" #include "net/url_request/url_request_test_util.h" class GURL; @@ -23,7 +23,7 @@ class SingleThreadTaskRunner; } // namespace base -namespace component_updater { +namespace update_client { #define POST_INTERCEPT_SCHEME "https" #define POST_INTERCEPT_HOSTNAME "localhost2" @@ -31,6 +31,25 @@ struct CrxComponent; +// component 1 has extension id "jebgalgnebhfojomionfpkfelancnnkf", and +// the RSA public key the following hash: +const uint8_t jebg_hash[] = {0x94, 0x16, 0x0b, 0x6d, 0x41, 0x75, 0xe9, 0xec, + 0x8e, 0xd5, 0xfa, 0x54, 0xb0, 0xd2, 0xdd, 0xa5, + 0x6e, 0x05, 0x6b, 0xe8, 0x73, 0x47, 0xf6, 0xc4, + 0x11, 0x9f, 0xbc, 0xb3, 0x09, 0xb3, 0x5b, 0x40}; +// component 2 has extension id "abagagagagagagagagagagagagagagag", and +// the RSA public key the following hash: +const uint8_t abag_hash[] = {0x01, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x01}; +// component 3 has extension id "ihfokbkgjpifnbbojhneepfflplebdkc", and +// the RSA public key the following hash: +const uint8_t ihfo_hash[] = {0x87, 0x5e, 0xa1, 0xa6, 0x9f, 0x85, 0xd1, 0x1e, + 0x97, 0xd4, 0x4f, 0x55, 0xbf, 0xb4, 0x13, 0xa2, + 0xe7, 0xc5, 0xc8, 0xf5, 0x60, 0x19, 0x78, 0x1b, + 0x6d, 0xe9, 0x4c, 0xeb, 0x96, 0x05, 0x42, 0x17}; + class TestConfigurator : public Configurator { public: TestConfigurator( @@ -83,6 +102,6 @@ DISALLOW_COPY_AND_ASSIGN(TestConfigurator); }; -} // namespace component_updater +} // namespace update_client -#endif // COMPONENTS_COMPONENT_UPDATER_TEST_TEST_CONFIGURATOR_H_ +#endif // COMPONENTS_UPDATE_CLIENT_TEST_TEST_CONFIGURATOR_H_
diff --git a/components/component_updater/test/test_installer.cc b/components/update_client/test/test_installer.cc similarity index 94% rename from components/component_updater/test/test_installer.cc rename to components/update_client/test/test_installer.cc index e70d67e..b6a3f843 100644 --- a/components/component_updater/test/test_installer.cc +++ b/components/update_client/test/test_installer.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 "components/component_updater/test/test_installer.h" +#include "components/update_client/test/test_installer.h" #include <string> @@ -10,7 +10,7 @@ #include "base/files/file_util.h" #include "base/values.h" -namespace component_updater { +namespace update_client { TestInstaller::TestInstaller() : error_(0), install_count_(0) { } @@ -83,4 +83,4 @@ return true; } -} // namespace component_updater +} // namespace update_client
diff --git a/components/component_updater/test/test_installer.h b/components/update_client/test/test_installer.h similarity index 85% rename from components/component_updater/test/test_installer.h rename to components/update_client/test/test_installer.h index e44c48d..933fe21 100644 --- a/components/component_updater/test/test_installer.h +++ b/components/update_client/test/test_installer.h
@@ -2,20 +2,20 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_COMPONENT_UPDATER_TEST_TEST_INSTALLER_H_ -#define CHROME_BROWSER_COMPONENT_UPDATER_TEST_TEST_INSTALLER_H_ +#ifndef COMPONENTS_UPDATE_CLIENT_TEST_TEST_INSTALLER_H_ +#define COMPONENTS_UPDATE_CLIENT_TEST_TEST_INSTALLER_H_ #include <string> #include "base/compiler_specific.h" #include "base/files/file_path.h" -#include "components/component_updater/component_updater_service.h" +#include "components/update_client/update_client.h" namespace base { class DictionaryValue; } -namespace component_updater { +namespace update_client { // A TestInstaller is an installer that does nothing for installation except // increment a counter. @@ -74,6 +74,6 @@ Version current_version_; }; -} // namespace component_updater +} // namespace update_client -#endif // CHROME_BROWSER_COMPONENT_UPDATER_TEST_TEST_INSTALLER_H_ +#endif // COMPONENTS_UPDATE_CLIENT_TEST_TEST_INSTALLER_H_
diff --git a/components/component_updater/test/update_checker_unittest.cc b/components/update_client/test/update_checker_unittest.cc similarity index 88% rename from components/component_updater/test/update_checker_unittest.cc rename to components/update_client/test/update_checker_unittest.cc index 051b4fb..20d3e79 100644 --- a/components/component_updater/test/update_checker_unittest.cc +++ b/components/update_client/test/update_checker_unittest.cc
@@ -13,25 +13,28 @@ #include "base/path_service.h" #include "base/run_loop.h" #include "base/version.h" -#include "components/component_updater/crx_update_item.h" -#include "components/component_updater/test/test_configurator.h" -#include "components/component_updater/test/url_request_post_interceptor.h" -#include "components/component_updater/update_checker.h" +#include "components/update_client/crx_update_item.h" +#include "components/update_client/test/test_configurator.h" +#include "components/update_client/test/url_request_post_interceptor.h" +#include "components/update_client/update_checker.h" #include "net/url_request/url_request_test_util.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" using std::string; -namespace component_updater { +namespace update_client { namespace { base::FilePath test_file(const char* file) { base::FilePath path; PathService::Get(base::DIR_SOURCE_ROOT, &path); - return path.AppendASCII("components").AppendASCII("test").AppendASCII("data") - .AppendASCII("component_updater").AppendASCII(file); + return path.AppendASCII("components") + .AppendASCII("test") + .AppendASCII("data") + .AppendASCII("update_client") + .AppendASCII(file); } } // namespace @@ -170,8 +173,7 @@ items_to_check.push_back(&item); update_checker_->CheckForUpdates( - items_to_check, - "extra=\"params\"", + items_to_check, "extra=\"params\"", base::Bind(&UpdateCheckerTest::UpdateCheckComplete, base::Unretained(this))); @@ -183,10 +185,8 @@ << post_interceptor_->GetRequestsAsString(); // Sanity check the request. - EXPECT_NE( - string::npos, - post_interceptor_->GetRequests()[0].find( - "request protocol=\"3.0\" extra=\"params\"")); + EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find( + "request protocol=\"3.0\" extra=\"params\"")); EXPECT_NE( string::npos, post_interceptor_->GetRequests()[0].find( @@ -218,10 +218,8 @@ items_to_check.push_back(&item); update_checker_->CheckForUpdates( - items_to_check, - "", - base::Bind(&UpdateCheckerTest::UpdateCheckComplete, - base::Unretained(this))); + items_to_check, "", base::Bind(&UpdateCheckerTest::UpdateCheckComplete, + base::Unretained(this))); RunThreads(); @@ -236,4 +234,4 @@ EXPECT_EQ(0ul, results_.list.size()); } -} // namespace component_updater +} // namespace update_client
diff --git a/components/component_updater/test/update_response_unittest.cc b/components/update_client/test/update_response_unittest.cc similarity index 98% rename from components/component_updater/test/update_response_unittest.cc rename to components/update_client/test/update_response_unittest.cc index 0a7070b..e106916 100644 --- a/components/component_updater/test/update_response_unittest.cc +++ b/components/update_client/test/update_response_unittest.cc
@@ -3,11 +3,11 @@ // found in the LICENSE file. #include "base/memory/scoped_vector.h" -#include "components/component_updater/update_response.h" +#include "components/update_client/update_response.h" #include "libxml/globals.h" #include "testing/gtest/include/gtest/gtest.h" -namespace component_updater { +namespace update_client { const char* kValidXml = "<?xml version='1.0' encoding='UTF-8'?>" @@ -122,7 +122,8 @@ // must be able to parse responses that include namespaces. const char* kUsesNamespacePrefix = "<?xml version='1.0' encoding='UTF-8'?>" - "<g:response xmlns:g='http://www.google.com/update2/response' protocol='3.0'>" + "<g:response xmlns:g='http://www.google.com/update2/response' " + "protocol='3.0'>" " <g:app appid='12345'>" " <g:updatecheck status='ok'>" " <g:urls>" @@ -298,4 +299,4 @@ EXPECT_EQ(firstResult->extension_id, "bbbbbbbb"); } -} // namespace component_updater +} // namespace update_client
diff --git a/components/component_updater/test/url_request_post_interceptor.cc b/components/update_client/test/url_request_post_interceptor.cc similarity index 92% rename from components/component_updater/test/url_request_post_interceptor.cc rename to components/update_client/test/url_request_post_interceptor.cc index f2dc839..4aeb7a7 100644 --- a/components/component_updater/test/url_request_post_interceptor.cc +++ b/components/update_client/test/url_request_post_interceptor.cc
@@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/component_updater/test/url_request_post_interceptor.h" +#include "components/update_client/test/url_request_post_interceptor.h" #include "base/files/file_util.h" #include "base/macros.h" #include "base/memory/scoped_ptr.h" #include "base/strings/stringprintf.h" -#include "components/component_updater/test/test_configurator.h" +#include "components/update_client/test/test_configurator.h" #include "net/base/upload_bytes_element_reader.h" #include "net/base/upload_data_stream.h" #include "net/url_request/url_request.h" @@ -17,7 +17,7 @@ #include "net/url_request/url_request_simple_job.h" #include "net/url_request/url_request_test_util.h" -namespace component_updater { +namespace update_client { // Returns a canned response. class URLRequestMockJob : public net::URLRequestSimpleJob { @@ -123,8 +123,7 @@ int i = 0; for (std::vector<std::string>::const_iterator it = requests.begin(); - it != requests.end(); - ++it) { + it != requests.end(); ++it) { s.append(base::StringPrintf("\n (%d): %s", ++i, it->c_str())); } @@ -154,8 +153,7 @@ void Unregister() { DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); for (InterceptorMap::iterator it = interceptors_.begin(); - it != interceptors_.end(); - ++it) + it != interceptors_.end(); ++it) delete (*it).second; net::URLRequestFilter::GetInstance()->RemoveHostnameHandler(scheme_, hostname_); @@ -218,8 +216,8 @@ interceptor->expectations_.pop(); ++interceptor->hit_count_; - return new URLRequestMockJob( - request, network_delegate, response_code, response_body); + return new URLRequestMockJob(request, network_delegate, response_code, + response_body); } } @@ -247,16 +245,14 @@ hostname, io_task_runner)) { io_task_runner_->PostTask( - FROM_HERE, - base::Bind(&URLRequestPostInterceptor::Delegate::Register, - base::Unretained(delegate_))); + FROM_HERE, base::Bind(&URLRequestPostInterceptor::Delegate::Register, + base::Unretained(delegate_))); } URLRequestPostInterceptorFactory::~URLRequestPostInterceptorFactory() { io_task_runner_->PostTask( - FROM_HERE, - base::Bind(&URLRequestPostInterceptor::Delegate::Unregister, - base::Unretained(delegate_))); + FROM_HERE, base::Bind(&URLRequestPostInterceptor::Delegate::Unregister, + base::Unretained(delegate_))); } URLRequestPostInterceptor* URLRequestPostInterceptorFactory::CreateInterceptor( @@ -269,8 +265,7 @@ bool res = io_task_runner_->PostTask( FROM_HERE, base::Bind(&URLRequestPostInterceptor::Delegate::OnCreateInterceptor, - base::Unretained(delegate_), - base::Unretained(interceptor))); + base::Unretained(delegate_), base::Unretained(interceptor))); if (!res) { delete interceptor; return NULL; @@ -303,4 +298,4 @@ base::FilePath::FromUTF8Unsafe(url_path)); } -} // namespace component_updater +} // namespace update_client
diff --git a/components/component_updater/test/url_request_post_interceptor.h b/components/update_client/test/url_request_post_interceptor.h similarity index 76% rename from components/component_updater/test/url_request_post_interceptor.h rename to components/update_client/test/url_request_post_interceptor.h index ffdcfb1..d261160 100644 --- a/components/component_updater/test/url_request_post_interceptor.h +++ b/components/update_client/test/url_request_post_interceptor.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 COMPONENTS_COMPONENT_UPDATER_TEST_URL_REQUEST_POST_INTERCEPTOR_H_ -#define COMPONENTS_COMPONENT_UPDATER_TEST_URL_REQUEST_POST_INTERCEPTOR_H_ +#ifndef COMPONENTS_UPDATE_CLIENT_TEST_URL_REQUEST_POST_INTERCEPTOR_H_ +#define COMPONENTS_UPDATE_CLIENT_TEST_URL_REQUEST_POST_INTERCEPTOR_H_ #include <stdint.h> #include <map> @@ -26,26 +26,7 @@ class URLRequest; } -namespace component_updater { - -// component 1 has extension id "jebgalgnebhfojomionfpkfelancnnkf", and -// the RSA public key the following hash: -const uint8_t jebg_hash[] = {0x94, 0x16, 0x0b, 0x6d, 0x41, 0x75, 0xe9, 0xec, - 0x8e, 0xd5, 0xfa, 0x54, 0xb0, 0xd2, 0xdd, 0xa5, - 0x6e, 0x05, 0x6b, 0xe8, 0x73, 0x47, 0xf6, 0xc4, - 0x11, 0x9f, 0xbc, 0xb3, 0x09, 0xb3, 0x5b, 0x40}; -// component 2 has extension id "abagagagagagagagagagagagagagagag", and -// the RSA public key the following hash: -const uint8_t abag_hash[] = {0x01, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x01}; -// component 3 has extension id "ihfokbkgjpifnbbojhneepfflplebdkc", and -// the RSA public key the following hash: -const uint8_t ihfo_hash[] = {0x87, 0x5e, 0xa1, 0xa6, 0x9f, 0x85, 0xd1, 0x1e, - 0x97, 0xd4, 0x4f, 0x55, 0xbf, 0xb4, 0x13, 0xa2, - 0xe7, 0xc5, 0xc8, 0xf5, 0x60, 0x19, 0x78, 0x1b, - 0x6d, 0xe9, 0x4c, 0xeb, 0x96, 0x05, 0x42, 0x17}; +namespace update_client { // Intercepts requests to a file path, counts them, and captures the body of // the requests. Optionally, for each request, it can return a canned response @@ -179,6 +160,6 @@ DISALLOW_COPY_AND_ASSIGN(PartialMatch); }; -} // namespace component_updater +} // namespace update_client -#endif // COMPONENTS_COMPONENT_UPDATER_TEST_URL_REQUEST_POST_INTERCEPTOR_H_ +#endif // COMPONENTS_UPDATE_CLIENT_TEST_URL_REQUEST_POST_INTERCEPTOR_H_
diff --git a/components/component_updater/update_checker.cc b/components/update_client/update_checker.cc similarity index 85% rename from components/component_updater/update_checker.cc rename to components/update_client/update_checker.cc index f14263c..9a38a5a 100644 --- a/components/component_updater/update_checker.cc +++ b/components/update_client/update_checker.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 "components/component_updater/update_checker.h" +#include "components/update_client/update_checker.h" #include <string> #include <vector> @@ -16,14 +16,14 @@ #include "base/memory/scoped_ptr.h" #include "base/strings/stringprintf.h" #include "base/threading/thread_checker.h" -#include "components/component_updater/component_updater_configurator.h" -#include "components/component_updater/component_updater_utils.h" -#include "components/component_updater/crx_update_item.h" -#include "components/component_updater/request_sender.h" +#include "components/update_client/configurator.h" +#include "components/update_client/crx_update_item.h" +#include "components/update_client/request_sender.h" +#include "components/update_client/utils.h" #include "net/url_request/url_fetcher.h" #include "url/gurl.h" -namespace component_updater { +namespace update_client { namespace { @@ -48,9 +48,7 @@ for (size_t i = 0; i != items.size(); ++i) { const CrxUpdateItem* item = items[i]; std::string app("<app "); - base::StringAppendF(&app, - "appid=\"%s\" version=\"%s\"", - item->id.c_str(), + base::StringAppendF(&app, "appid=\"%s\" version=\"%s\"", item->id.c_str(), item->component.version.GetString().c_str()); if (item->on_demand) base::StringAppendF(&app, " installsource=\"ondemand\""); @@ -69,10 +67,8 @@ } return BuildProtocolRequest(config.GetBrowserVersion().GetString(), - config.GetChannel(), - config.GetLang(), - config.GetOSLongName(), - app_elements, + config.GetChannel(), config.GetLang(), + config.GetOSLongName(), app_elements, additional_attributes); } @@ -154,8 +150,8 @@ } request_sender_.reset(); - update_check_callback_.Run( - original_url, error, error_message, update_response.results()); + update_check_callback_.Run(original_url, error, error_message, + update_response.results()); } } // namespace @@ -164,4 +160,4 @@ return scoped_ptr<UpdateChecker>(new UpdateCheckerImpl(config)); } -} // namespace component_updater +} // namespace update_client
diff --git a/components/component_updater/update_checker.h b/components/update_client/update_checker.h similarity index 81% rename from components/component_updater/update_checker.h rename to components/update_client/update_checker.h index 742aed7..1ac6426 100644 --- a/components/component_updater/update_checker.h +++ b/components/update_client/update_checker.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 COMPONENTS_COMPONENT_UPDATER_UPDATE_CHECKER_H_ -#define COMPONENTS_COMPONENT_UPDATER_UPDATE_CHECKER_H_ +#ifndef COMPONENTS_UPDATE_CLIENT_UPDATE_CHECKER_H_ +#define COMPONENTS_UPDATE_CLIENT_UPDATE_CHECKER_H_ #include <string> #include <vector> @@ -11,7 +11,7 @@ #include "base/callback.h" #include "base/macros.h" #include "base/memory/scoped_ptr.h" -#include "components/component_updater/update_response.h" +#include "components/update_client/update_response.h" #include "url/gurl.h" class GURL; @@ -20,7 +20,7 @@ class URLRequestContextGetter; } -namespace component_updater { +namespace update_client { class Configurator; struct CrxUpdateItem; @@ -52,6 +52,6 @@ DISALLOW_COPY_AND_ASSIGN(UpdateChecker); }; -} // namespace component_updater +} // namespace update_client -#endif // COMPONENTS_COMPONENT_UPDATER_UPDATE_CHECKER_H_ +#endif // COMPONENTS_UPDATE_CLIENT_UPDATE_CHECKER_H_
diff --git a/components/update_client/update_client.cc b/components/update_client/update_client.cc new file mode 100644 index 0000000..b7fff2b5 --- /dev/null +++ b/components/update_client/update_client.cc
@@ -0,0 +1,33 @@ +// 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 "components/update_client/update_client.h" + +#include "components/update_client/crx_update_item.h" + +namespace update_client { + +CrxUpdateItem::CrxUpdateItem() + : status(kNew), + on_demand(false), + diff_update_failed(false), + error_category(0), + error_code(0), + extra_code1(0), + diff_error_category(0), + diff_error_code(0), + diff_extra_code1(0) { +} + +CrxUpdateItem::~CrxUpdateItem() { +} + +CrxComponent::CrxComponent() + : installer(NULL), allow_background_download(true) { +} + +CrxComponent::~CrxComponent() { +} + +} // namespace update_client
diff --git a/components/update_client/update_client.h b/components/update_client/update_client.h new file mode 100644 index 0000000..07b5617 --- /dev/null +++ b/components/update_client/update_client.h
@@ -0,0 +1,71 @@ +// Copyright 2015 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_UPDATE_CLIENT_UPDATE_CLIENT_H_ +#define COMPONENTS_UPDATE_CLIENT_UPDATE_CLIENT_H_ + +#include <stdint.h> +#include <string> +#include <vector> + +#include "base/version.h" + +namespace base { +class DictionaryValue; +class FilePath; +} + +namespace update_client { + +// Component specific installers must derive from this class and implement +// OnUpdateError() and Install(). A valid instance of this class must be +// given to ComponentUpdateService::RegisterComponent(). +class ComponentInstaller { + public: + // Called by the component updater on the main thread when there was a + // problem unpacking or verifying the component. |error| is a non-zero + // value which is only meaningful to the component updater. + virtual void OnUpdateError(int error) = 0; + + // Called by the component updater when a component has been unpacked + // and is ready to be installed. |manifest| contains the CRX manifest + // json dictionary and |unpack_path| contains the temporary directory + // with all the unpacked CRX files. This method may be called from + // a thread other than the main thread. + virtual bool Install(const base::DictionaryValue& manifest, + const base::FilePath& unpack_path) = 0; + + // Set |installed_file| to the full path to the installed |file|. |file| is + // the filename of the file in this component's CRX. Returns false if this is + // not possible (the file has been removed or modified, or its current + // location is unknown). Otherwise, returns true. + virtual bool GetInstalledFile(const std::string& file, + base::FilePath* installed_file) = 0; + + virtual ~ComponentInstaller() {} +}; + +// Describes a particular component that can be installed or updated. This +// structure is required to register a component with the component updater. +// |pk_hash| is the SHA256 hash of the component's public key. If the component +// is to be installed then version should be "0" or "0.0", else it should be +// the current version. |fingerprint|, and |name| are optional. +// |allow_background_download| specifies that the component can be background +// downloaded in some cases. The default for this value is |true| and the value +// can be overriden at the registration time. This is a temporary change until +// the issue 340448 is resolved. +struct CrxComponent { + std::vector<uint8_t> pk_hash; + ComponentInstaller* installer; + Version version; + std::string fingerprint; + std::string name; + bool allow_background_download; + CrxComponent(); + ~CrxComponent(); +}; + +} // namespace update_client + +#endif // COMPONENTS_UPDATE_CLIENT_UPDATE_CLIENT_H_
diff --git a/components/component_updater/update_response.cc b/components/update_client/update_response.cc similarity index 94% rename from components/component_updater/update_response.cc rename to components/update_client/update_response.cc index c37c45b..8677fe6 100644 --- a/components/component_updater/update_response.cc +++ b/components/update_client/update_response.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 "components/component_updater/update_response.h" +#include "components/update_client/update_response.h" #include <algorithm> @@ -15,25 +15,35 @@ #include "libxml/tree.h" #include "third_party/libxml/chromium/libxml_utils.h" -namespace component_updater { +namespace update_client { static const char* kExpectedResponseProtocol = "3.0"; -UpdateResponse::UpdateResponse() {} -UpdateResponse::~UpdateResponse() {} +UpdateResponse::UpdateResponse() { +} +UpdateResponse::~UpdateResponse() { +} -UpdateResponse::Results::Results() : daystart_elapsed_seconds(kNoDaystart) {} -UpdateResponse::Results::~Results() {} +UpdateResponse::Results::Results() : daystart_elapsed_seconds(kNoDaystart) { +} +UpdateResponse::Results::~Results() { +} -UpdateResponse::Result::Result() {} +UpdateResponse::Result::Result() { +} -UpdateResponse::Result::~Result() {} +UpdateResponse::Result::~Result() { +} -UpdateResponse::Result::Manifest::Manifest() {} -UpdateResponse::Result::Manifest::~Manifest() {} +UpdateResponse::Result::Manifest::Manifest() { +} +UpdateResponse::Result::Manifest::~Manifest() { +} -UpdateResponse::Result::Manifest::Package::Package() : size(0), sizediff(0) {} -UpdateResponse::Result::Manifest::Package::~Package() {} +UpdateResponse::Result::Manifest::Package::Package() : size(0), sizediff(0) { +} +UpdateResponse::Result::Manifest::Package::~Package() { +} void UpdateResponse::ParseError(const char* details, ...) { va_list args; @@ -336,4 +346,4 @@ return true; } -} // namespace component_updater +} // namespace update_client
diff --git a/components/component_updater/update_response.h b/components/update_client/update_response.h similarity index 93% rename from components/component_updater/update_response.h rename to components/update_client/update_response.h index c264696b..003474f 100644 --- a/components/component_updater/update_response.h +++ b/components/update_client/update_response.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 COMPONENTS_COMPONENT_UPDATER_UPDATE_RESPONSE_H_ -#define COMPONENTS_COMPONENT_UPDATER_UPDATE_RESPONSE_H_ +#ifndef COMPONENTS_UPDATE_CLIENT_UPDATE_RESPONSE_H_ +#define COMPONENTS_UPDATE_CLIENT_UPDATE_RESPONSE_H_ #include <string> #include <vector> @@ -11,7 +11,7 @@ #include "base/macros.h" #include "url/gurl.h" -namespace component_updater { +namespace update_client { // Parses responses for the update protocol version 3. // (http://code.google.com/p/omaha/wiki/ServerProtocol) @@ -130,6 +130,6 @@ DISALLOW_COPY_AND_ASSIGN(UpdateResponse); }; -} // namespace component_updater +} // namespace update_client -#endif // COMPONENTS_COMPONENT_UPDATER_UPDATE_RESPONSE_H_ +#endif // COMPONENTS_UPDATE_CLIENT_UPDATE_RESPONSE_H_
diff --git a/components/component_updater/url_fetcher_downloader.cc b/components/update_client/url_fetcher_downloader.cc similarity index 94% rename from components/component_updater/url_fetcher_downloader.cc rename to components/update_client/url_fetcher_downloader.cc index 2eeb3f1..fd7f3da 100644 --- a/components/component_updater/url_fetcher_downloader.cc +++ b/components/update_client/url_fetcher_downloader.cc
@@ -2,18 +2,18 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/component_updater/url_fetcher_downloader.h" +#include "components/update_client/url_fetcher_downloader.h" #include <stdint.h> #include "base/logging.h" #include "base/sequenced_task_runner.h" -#include "components/component_updater/component_updater_utils.h" +#include "components/update_client/utils.h" #include "net/base/load_flags.h" #include "net/url_request/url_fetcher.h" #include "url/gurl.h" -namespace component_updater { +namespace update_client { UrlFetcherDownloader::UrlFetcherDownloader( scoped_ptr<CrxDownloader> successor, @@ -106,4 +106,4 @@ OnDownloadProgress(result); } -} // namespace component_updater +} // namespace update_client
diff --git a/components/component_updater/url_fetcher_downloader.h b/components/update_client/url_fetcher_downloader.h similarity index 83% rename from components/component_updater/url_fetcher_downloader.h rename to components/update_client/url_fetcher_downloader.h index 99a7d3a..7a8e3b2 100644 --- a/components/component_updater/url_fetcher_downloader.h +++ b/components/update_client/url_fetcher_downloader.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 COMPONENTS_COMPONENT_UPDATER_URL_FETCHER_DOWNLOADER_H_ -#define COMPONENTS_COMPONENT_UPDATER_URL_FETCHER_DOWNLOADER_H_ +#ifndef COMPONENTS_UPDATE_CLIENT_URL_FETCHER_DOWNLOADER_H_ +#define COMPONENTS_UPDATE_CLIENT_URL_FETCHER_DOWNLOADER_H_ #include <stdint.h> @@ -12,7 +12,7 @@ #include "base/memory/scoped_ptr.h" #include "base/threading/thread_checker.h" #include "base/time/time.h" -#include "components/component_updater/crx_downloader.h" +#include "components/update_client/crx_downloader.h" #include "net/url_request/url_fetcher_delegate.h" namespace net { @@ -20,7 +20,7 @@ class URLRequestContextGetter; } -namespace component_updater { +namespace update_client { // Implements a CRX downloader in top of the URLFetcher. class UrlFetcherDownloader : public CrxDownloader, @@ -55,6 +55,6 @@ DISALLOW_COPY_AND_ASSIGN(UrlFetcherDownloader); }; -} // namespace component_updater +} // namespace update_client -#endif // COMPONENTS_COMPONENT_UPDATER_URL_FETCHER_DOWNLOADER_H_ +#endif // COMPONENTS_UPDATE_CLIENT_URL_FETCHER_DOWNLOADER_H_
diff --git a/components/component_updater/component_updater_utils.cc b/components/update_client/utils.cc similarity index 92% rename from components/component_updater/component_updater_utils.cc rename to components/update_client/utils.cc index 56e33ac0..47bb4377 100644 --- a/components/component_updater/component_updater_utils.cc +++ b/components/update_client/utils.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 "components/component_updater/component_updater_utils.h" +#include "components/update_client/utils.h" #include <stdint.h> #include <cmath> @@ -16,18 +16,17 @@ #include "base/strings/stringprintf.h" #include "base/sys_info.h" #include "base/win/windows_version.h" -#include "components/component_updater/component_updater_configurator.h" -#include "components/component_updater/crx_update_item.h" #include "components/crx_file/id_util.h" +#include "components/update_client/configurator.h" +#include "components/update_client/crx_update_item.h" +#include "components/update_client/update_client.h" #include "components/update_client/update_query_params.h" #include "net/base/load_flags.h" #include "net/url_request/url_fetcher.h" #include "net/url_request/url_request_context_getter.h" #include "net/url_request/url_request_status.h" -using update_client::UpdateQueryParams; - -namespace component_updater { +namespace update_client { namespace { @@ -100,14 +99,12 @@ base::StringAppendF(&request, ">"); // HW platform information. - base::StringAppendF(&request, - "<hw physmemory=\"%d\"/>", + base::StringAppendF(&request, "<hw physmemory=\"%d\"/>", GetPhysicalMemoryGB()); // "physmem" in GB. // OS version and platform information. base::StringAppendF( - &request, - "<os platform=\"%s\" version=\"%s\" arch=\"%s\"/>", + &request, "<os platform=\"%s\" version=\"%s\" arch=\"%s\"/>", os_long_name.c_str(), // "platform" base::SysInfo().OperatingSystemVersion().c_str(), // "version" base::SysInfo().OperatingSystemArchitecture().c_str()); // "arch" @@ -195,4 +192,4 @@ base::HexEncode(&component.pk_hash[0], kCrxIdSize))); } -} // namespace component_updater +} // namespace update_client
diff --git a/components/component_updater/component_updater_utils.h b/components/update_client/utils.h similarity index 92% rename from components/component_updater/component_updater_utils.h rename to components/update_client/utils.h index ad2b598..297eb97 100644 --- a/components/component_updater/component_updater_utils.h +++ b/components/update_client/utils.h
@@ -2,12 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_COMPONENT_UPDATER_COMPONENT_UPDATER_UTILS_H_ -#define COMPONENTS_COMPONENT_UPDATER_COMPONENT_UPDATER_UTILS_H_ +#ifndef COMPONENTS_UPDATE_CLIENT_UTILS_H_ +#define COMPONENTS_UPDATE_CLIENT_UTILS_H_ #include <string> -struct CrxComponent; class GURL; namespace base { @@ -20,9 +19,10 @@ class URLRequestContextGetter; } -namespace component_updater { +namespace update_client { class Configurator; +struct CrxComponent; struct CrxUpdateItem; // An update protocol request starts with a common preamble which includes @@ -85,6 +85,6 @@ // format similar with the format of an extension id. std::string GetCrxComponentID(const CrxComponent& component); -} // namespace component_updater +} // namespace update_client -#endif // COMPONENTS_COMPONENT_UPDATER_COMPONENT_UPDATER_UTILS_H_ +#endif // COMPONENTS_UPDATE_CLIENT_UTILS_H_
diff --git a/components/user_manager/user.cc b/components/user_manager/user.cc index ebef979..f460af3 100644 --- a/components/user_manager/user.cc +++ b/components/user_manager/user.cc
@@ -38,12 +38,12 @@ class RegularUser : public User { public: explicit RegularUser(const std::string& email); - virtual ~RegularUser(); + ~RegularUser() override; // Overridden from User: - virtual UserType GetType() const override; - virtual bool CanSyncImage() const override; - virtual void SetIsChild(bool is_child) override; + UserType GetType() const override; + bool CanSyncImage() const override; + void SetIsChild(bool is_child) override; private: bool is_child_; @@ -54,10 +54,10 @@ class GuestUser : public User { public: GuestUser(); - virtual ~GuestUser(); + ~GuestUser() override; // Overridden from User: - virtual UserType GetType() const override; + UserType GetType() const override; private: DISALLOW_COPY_AND_ASSIGN(GuestUser); @@ -66,10 +66,10 @@ class KioskAppUser : public User { public: explicit KioskAppUser(const std::string& app_id); - virtual ~KioskAppUser(); + ~KioskAppUser() override; // Overridden from User: - virtual UserType GetType() const override; + UserType GetType() const override; private: DISALLOW_COPY_AND_ASSIGN(KioskAppUser); @@ -78,11 +78,11 @@ class SupervisedUser : public User { public: explicit SupervisedUser(const std::string& username); - virtual ~SupervisedUser(); + ~SupervisedUser() override; // Overridden from User: - virtual UserType GetType() const override; - virtual std::string display_email() const override; + UserType GetType() const override; + std::string display_email() const override; private: DISALLOW_COPY_AND_ASSIGN(SupervisedUser); @@ -91,10 +91,10 @@ class PublicAccountUser : public User { public: explicit PublicAccountUser(const std::string& email); - virtual ~PublicAccountUser(); + ~PublicAccountUser() override; // Overridden from User: - virtual UserType GetType() const override; + UserType GetType() const override; private: DISALLOW_COPY_AND_ASSIGN(PublicAccountUser);
diff --git a/components/user_manager/user_manager_base.cc b/components/user_manager/user_manager_base.cc index 08f5a07..d10f956 100644 --- a/components/user_manager/user_manager_base.cc +++ b/components/user_manager/user_manager_base.cc
@@ -982,10 +982,11 @@ void UserManagerBase::ChangeUserChildStatus(User* user, bool is_child) { DCHECK(task_runner_->RunsTasksOnCurrentThread()); + if (user->IsSupervised() == is_child) + return; user->SetIsChild(is_child); - SaveUserType(user->email(), is_child - ? user_manager::USER_TYPE_CHILD - : user_manager::USER_TYPE_REGULAR); + SaveUserType(user->email(), is_child ? user_manager::USER_TYPE_CHILD + : user_manager::USER_TYPE_REGULAR); FOR_EACH_OBSERVER(UserManager::UserSessionStateObserver, session_state_observer_list_, UserChangedChildStatus(user));
diff --git a/components/user_manager/user_manager_base.h b/components/user_manager/user_manager_base.h index d9944cd..ba7cd793 100644 --- a/components/user_manager/user_manager_base.h +++ b/components/user_manager/user_manager_base.h
@@ -38,75 +38,71 @@ // |blocking_task_runner| for SequencedWorkerPool. UserManagerBase(scoped_refptr<base::TaskRunner> task_runner, scoped_refptr<base::TaskRunner> blocking_task_runner); - virtual ~UserManagerBase(); + ~UserManagerBase() override; // Registers UserManagerBase preferences. static void RegisterPrefs(PrefRegistrySimple* registry); // UserManager implementation: - virtual void Shutdown() override; - virtual const UserList& GetUsers() const override; - virtual const UserList& GetLoggedInUsers() const override; - virtual const UserList& GetLRULoggedInUsers() const override; - virtual const std::string& GetOwnerEmail() const override; - virtual void UserLoggedIn(const std::string& user_id, - const std::string& user_id_hash, - bool browser_restart) override; - virtual void SwitchActiveUser(const std::string& user_id) override; - virtual void SwitchToLastActiveUser() override; - virtual void SessionStarted() override; - virtual void RemoveUser(const std::string& user_id, - RemoveUserDelegate* delegate) override; - virtual void RemoveUserFromList(const std::string& user_id) override; - virtual bool IsKnownUser(const std::string& user_id) const override; - virtual const User* FindUser(const std::string& user_id) const override; - virtual User* FindUserAndModify(const std::string& user_id) override; - virtual const User* GetLoggedInUser() const override; - virtual User* GetLoggedInUser() override; - virtual const User* GetActiveUser() const override; - virtual User* GetActiveUser() override; - virtual const User* GetPrimaryUser() const override; - virtual void SaveUserOAuthStatus( - const std::string& user_id, - User::OAuthTokenStatus oauth_token_status) override; - virtual void SaveForceOnlineSignin(const std::string& user_id, - bool force_online_signin) override; - virtual void SaveUserDisplayName(const std::string& user_id, - const base::string16& display_name) override; - virtual base::string16 GetUserDisplayName( + void Shutdown() override; + const UserList& GetUsers() const override; + const UserList& GetLoggedInUsers() const override; + const UserList& GetLRULoggedInUsers() const override; + const std::string& GetOwnerEmail() const override; + void UserLoggedIn(const std::string& user_id, + const std::string& user_id_hash, + bool browser_restart) override; + void SwitchActiveUser(const std::string& user_id) override; + void SwitchToLastActiveUser() override; + void SessionStarted() override; + void RemoveUser(const std::string& user_id, + RemoveUserDelegate* delegate) override; + void RemoveUserFromList(const std::string& user_id) override; + bool IsKnownUser(const std::string& user_id) const override; + const User* FindUser(const std::string& user_id) const override; + User* FindUserAndModify(const std::string& user_id) override; + const User* GetLoggedInUser() const override; + User* GetLoggedInUser() override; + const User* GetActiveUser() const override; + User* GetActiveUser() override; + const User* GetPrimaryUser() const override; + void SaveUserOAuthStatus(const std::string& user_id, + User::OAuthTokenStatus oauth_token_status) override; + void SaveForceOnlineSignin(const std::string& user_id, + bool force_online_signin) override; + void SaveUserDisplayName(const std::string& user_id, + const base::string16& display_name) override; + base::string16 GetUserDisplayName(const std::string& user_id) const override; + void SaveUserDisplayEmail(const std::string& user_id, + const std::string& display_email) override; + std::string GetUserDisplayEmail(const std::string& user_id) const override; + void SaveUserType(const std::string& user_id, + const UserType& user_type) override; + void UpdateUserAccountData(const std::string& user_id, + const UserAccountData& account_data) override; + bool IsCurrentUserOwner() const override; + bool IsCurrentUserNew() const override; + bool IsCurrentUserNonCryptohomeDataEphemeral() const override; + bool CanCurrentUserLock() const override; + bool IsUserLoggedIn() const override; + bool IsLoggedInAsUserWithGaiaAccount() const override; + bool IsLoggedInAsChildUser() const override; + bool IsLoggedInAsPublicAccount() const override; + bool IsLoggedInAsGuest() const override; + bool IsLoggedInAsSupervisedUser() const override; + bool IsLoggedInAsKioskApp() const override; + bool IsLoggedInAsStub() const override; + bool IsSessionStarted() const override; + bool IsUserNonCryptohomeDataEphemeral( const std::string& user_id) const override; - virtual void SaveUserDisplayEmail(const std::string& user_id, - const std::string& display_email) override; - virtual std::string GetUserDisplayEmail( - const std::string& user_id) const override; - virtual void SaveUserType(const std::string& user_id, - const UserType& user_type) override; - virtual void UpdateUserAccountData( - const std::string& user_id, - const UserAccountData& account_data) override; - virtual bool IsCurrentUserOwner() const override; - virtual bool IsCurrentUserNew() const override; - virtual bool IsCurrentUserNonCryptohomeDataEphemeral() const override; - virtual bool CanCurrentUserLock() const override; - virtual bool IsUserLoggedIn() const override; - virtual bool IsLoggedInAsUserWithGaiaAccount() const override; - virtual bool IsLoggedInAsChildUser() const override; - virtual bool IsLoggedInAsPublicAccount() const override; - virtual bool IsLoggedInAsGuest() const override; - virtual bool IsLoggedInAsSupervisedUser() const override; - virtual bool IsLoggedInAsKioskApp() const override; - virtual bool IsLoggedInAsStub() const override; - virtual bool IsSessionStarted() const override; - virtual bool IsUserNonCryptohomeDataEphemeral( - const std::string& user_id) const override; - virtual void AddObserver(UserManager::Observer* obs) override; - virtual void RemoveObserver(UserManager::Observer* obs) override; - virtual void AddSessionStateObserver( + void AddObserver(UserManager::Observer* obs) override; + void RemoveObserver(UserManager::Observer* obs) override; + void AddSessionStateObserver( UserManager::UserSessionStateObserver* obs) override; - virtual void RemoveSessionStateObserver( + void RemoveSessionStateObserver( UserManager::UserSessionStateObserver* obs) override; - virtual void NotifyLocalStateChanged() override; - virtual void ChangeUserChildStatus(User* user, bool is_child) override; + void NotifyLocalStateChanged() override; + void ChangeUserChildStatus(User* user, bool is_child) override; // Helper function that copies users from |users_list| to |users_vector| and // |users_set|. Duplicates and users already present in |existing_users| are
diff --git a/components/wifi_sync/BUILD.gn b/components/wifi_sync/BUILD.gn index 324bc8a..03444289 100644 --- a/components/wifi_sync/BUILD.gn +++ b/components/wifi_sync/BUILD.gn
@@ -33,11 +33,13 @@ deps = [ ":wifi_sync", "//sync", + "//testing/gmock", "//testing/gtest", ] sources = [ "wifi_config_delegate_chromeos_unittest.cc", + "wifi_credential_syncable_service_unittest.cc", "wifi_credential_unittest.cc", "wifi_security_class_chromeos_unittest.cc", "wifi_security_class_unittest.cc",
diff --git a/components/wifi_sync/DEPS b/components/wifi_sync/DEPS index c9d0bc0..441abe4 100644 --- a/components/wifi_sync/DEPS +++ b/components/wifi_sync/DEPS
@@ -1,10 +1,12 @@ include_rules = [ "+chromeos/dbus", + "+chromeos/login", "+chromeos/network", "+components/keyed_service/content", "+components/keyed_service/core", "+components/onc", "+sync/api", + "+sync/internal_api/public/attachments", "+sync/protocol", "+third_party/cros_system_api/dbus/service_constants.h", ]
diff --git a/components/wifi_sync/wifi_credential_syncable_service.cc b/components/wifi_sync/wifi_credential_syncable_service.cc index a78b92a..e4023019 100644 --- a/components/wifi_sync/wifi_credential_syncable_service.cc +++ b/components/wifi_sync/wifi_credential_syncable_service.cc
@@ -4,18 +4,111 @@ #include "components/wifi_sync/wifi_credential_syncable_service.h" +#include <stdint.h> +#include <vector> + #include "base/logging.h" +#include "components/wifi_sync/wifi_credential.h" +#include "components/wifi_sync/wifi_security_class.h" #include "sync/api/sync_change.h" +#include "sync/api/sync_data.h" #include "sync/api/sync_error.h" #include "sync/api/sync_error_factory.h" #include "sync/api/sync_merge_result.h" +#include "sync/protocol/sync.pb.h" namespace wifi_sync { +namespace { + +struct RawCredentialData { + std::vector<uint8_t> ssid; + WifiSecurityClass security_class; + std::string passphrase; +}; + +void BuildSpecifics(const WifiCredential& credential, + sync_pb::EntitySpecifics* out_buffer) { + DCHECK(out_buffer); + sync_pb::WifiCredentialSpecifics* credential_specifics = + out_buffer->mutable_wifi_credential(); + DCHECK(credential_specifics); + credential_specifics->set_ssid(credential.ssid().data(), + credential.ssid().size()); + credential_specifics->set_security_class( + WifiSecurityClassToSyncSecurityClass(credential.security_class())); + if (WifiSecurityClassSupportsPassphrases(credential.security_class())) { + credential_specifics->set_passphrase(credential.passphrase().data(), + credential.passphrase().size()); + } +} + +bool ParseSpecifics(const sync_pb::EntitySpecifics& specifics, + RawCredentialData* raw_credential) { + DCHECK(raw_credential); + if (!specifics.has_wifi_credential()) { + LOG(ERROR) << "Specifics with missing wifi_credential; skipping"; + return false; + } + + const sync_pb::WifiCredentialSpecifics& credential_specifics = + specifics.wifi_credential(); + if (!credential_specifics.has_ssid()) { + LOG(ERROR) << "Specifics with missing SSID; skipping"; + return false; + } + if (!credential_specifics.has_security_class()) { + LOG(ERROR) << "Specifics with missing security class; skipping"; + return false; + } + + const WifiSecurityClass security_class = + WifiSecurityClassFromSyncSecurityClass( + credential_specifics.security_class()); + if (WifiSecurityClassSupportsPassphrases(security_class) && + !credential_specifics.has_passphrase()) { + LOG(ERROR) << "Specifics for security class " + << credential_specifics.security_class() + << " is missing passphrase; skipping"; + return false; + } + + raw_credential->ssid.assign(credential_specifics.ssid().begin(), + credential_specifics.ssid().end()); + raw_credential->security_class = security_class; + raw_credential->passphrase = credential_specifics.passphrase(); + return true; +} + +// TODO(quiche): Separate SyncData validation from parsing of +// WifiCredentialSpecifics. +bool ParseSyncData(const syncer::SyncData& sync_data, + RawCredentialData* raw_credential) { + DCHECK(raw_credential); + if (!sync_data.IsValid()) { + LOG(WARNING) << "Invalid SyncData; skipping item"; + return false; + } + + if (sync_data.GetDataType() != syncer::WIFI_CREDENTIALS) { + LOG(WARNING) << "Unexpected SyncData of type " + << syncer::ModelTypeToString(sync_data.GetDataType()) + << "; skipping item"; + return false; + } + + return ParseSpecifics(sync_data.GetSpecifics(), raw_credential); +} + +} // namespace + const syncer::ModelType WifiCredentialSyncableService::kModelType = syncer::WIFI_CREDENTIALS; -WifiCredentialSyncableService::WifiCredentialSyncableService() { +WifiCredentialSyncableService::WifiCredentialSyncableService( + scoped_ptr<WifiConfigDelegate> network_config_delegate) + : network_config_delegate_(network_config_delegate.Pass()) { + DCHECK(network_config_delegate_); } WifiCredentialSyncableService::~WifiCredentialSyncableService() { @@ -32,7 +125,7 @@ sync_processor_ = sync_processor.Pass(); - // TODO(quiche): Update local WiFi configuration. + // TODO(quiche): Update local WiFi configuration from |initial_sync_data|. // TODO(quiche): Notify upper layers that sync is ready. NOTIMPLEMENTED(); @@ -54,8 +147,78 @@ syncer::SyncError WifiCredentialSyncableService::ProcessSyncChanges( const tracked_objects::Location& /* caller_location */, const syncer::SyncChangeList& change_list) { - NOTIMPLEMENTED(); + if (!sync_processor_.get()) { + return syncer::SyncError( + FROM_HERE, syncer::SyncError::UNREADY_ERROR, + "ProcessSyncChanges called before MergeDataAndStartSyncing", + kModelType); + } + + for (const syncer::SyncChange& sync_change : change_list) { + DCHECK(sync_change.IsValid()); + RawCredentialData raw_credential; + if (!ParseSyncData(sync_change.sync_data(), &raw_credential)) { + LOG(WARNING) << "Failed to parse item; skipping " + << syncer::SyncChange::ChangeTypeToString( + sync_change.change_type()); + continue; + } + + scoped_ptr<WifiCredential> credential; + switch (sync_change.change_type()) { + case syncer::SyncChange::ACTION_ADD: + credential = WifiCredential::Create(raw_credential.ssid, + raw_credential.security_class, + raw_credential.passphrase); + if (!credential) + LOG(WARNING) << "Failed to create credential; skipping"; + else + network_config_delegate_->AddToLocalNetworks(*credential); + break; + case syncer::SyncChange::ACTION_UPDATE: + // TODO(quiche): Implement update, and add appropriate tests. + NOTIMPLEMENTED(); + break; + case syncer::SyncChange::ACTION_DELETE: + // TODO(quiche): Implement delete, and add appropriate tests. + NOTIMPLEMENTED(); + break; + default: + return syncer::SyncError( + FROM_HERE, syncer::SyncError::DATATYPE_ERROR, + "ProcessSyncChanges given invalid SyncChangeType", kModelType); + } + } + return syncer::SyncError(); } +bool WifiCredentialSyncableService::AddToSyncedNetworks( + const std::string& item_id, + const WifiCredential& credential) { + if (!sync_processor_.get()) { + // Callers must queue updates until MergeDataAndStartSyncing has + // been called on this SyncableService. + LOG(WARNING) << "WifiCredentials syncable service is not started."; + return false; + } + + // TODO(quiche): Handle case where network already exists. + syncer::SyncChangeList change_list; + syncer::SyncError sync_error; + sync_pb::EntitySpecifics wifi_credential_specifics; + BuildSpecifics(credential, &wifi_credential_specifics); + change_list.push_back( + syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_ADD, + syncer::SyncData::CreateLocalData( + item_id, item_id, wifi_credential_specifics))); + sync_error = sync_processor_->ProcessSyncChanges(FROM_HERE, change_list); + if (sync_error.IsSet()) { + LOG(ERROR) << sync_error.ToString(); + return false; + } + + return true; +} + } // namespace wifi_sync
diff --git a/components/wifi_sync/wifi_credential_syncable_service.h b/components/wifi_sync/wifi_credential_syncable_service.h index fbd82f4b..d0868e8 100644 --- a/components/wifi_sync/wifi_credential_syncable_service.h +++ b/components/wifi_sync/wifi_credential_syncable_service.h
@@ -5,13 +5,17 @@ #ifndef COMPONENTS_WIFI_SYNC_WIFI_CREDENTIAL_SYNCABLE_SERVICE_H_ #define COMPONENTS_WIFI_SYNC_WIFI_CREDENTIAL_SYNCABLE_SERVICE_H_ +#include <string> + #include "base/macros.h" #include "base/memory/scoped_ptr.h" #include "components/keyed_service/core/keyed_service.h" +#include "components/wifi_sync/wifi_config_delegate.h" #include "sync/api/sync_change_processor.h" #include "sync/api/syncable_service.h" namespace wifi_sync { +class WifiCredential; // KeyedService that synchronizes WiFi credentials between local settings, // and Chrome Sync. @@ -19,10 +23,19 @@ // This service does not necessarily own the storage for WiFi // credentials. In particular, on ChromeOS, WiFi credential storage is // managed by the ChromeOS connection manager ("Shill"). +// +// On ChromeOS, this class should only be instantiated +// for the primary user profile, as that is the only profile for +// which a Shill profile is loaded. class WifiCredentialSyncableService : public syncer::SyncableService, public KeyedService { public: - WifiCredentialSyncableService(); + // Constructs a syncable service. Changes from Chrome Sync will be + // applied locally by |network_config_delegate|. Local changes will + // be propagated to Chrome Sync using the |sync_processor| provided + // in the call to MergeDataAndStartSyncing. + explicit WifiCredentialSyncableService( + scoped_ptr<WifiConfigDelegate> network_config_delegate); ~WifiCredentialSyncableService() override; // syncer::SyncableService implementation. @@ -37,11 +50,25 @@ const tracked_objects::Location& caller_location, const syncer::SyncChangeList& change_list) override; + // Adds a WiFiCredential to Chrome Sync. |item_id| is a persistent + // identifier which can be used to later remove the credential. It + // is an error to add a network that already exists. It is also an + // error to call this method before MergeDataAndStartSyncing(), or + // after StopSyncing(). + // + // TODO(quiche): Allow changing a credential, by addding it again. + // crbug.com/431436 + bool AddToSyncedNetworks(const std::string& item_id, + const WifiCredential& credential); + private: // The syncer::ModelType that this SyncableService processes and // generates updates for. static const syncer::ModelType kModelType; + // The object we use to change local network configuration. + const scoped_ptr<WifiConfigDelegate> network_config_delegate_; + // Our SyncChangeProcessor instance. Used to push changes into // Chrome Sync. scoped_ptr<syncer::SyncChangeProcessor> sync_processor_;
diff --git a/components/wifi_sync/wifi_credential_syncable_service_factory.cc b/components/wifi_sync/wifi_credential_syncable_service_factory.cc index dbc2fec..cf3b460 100644 --- a/components/wifi_sync/wifi_credential_syncable_service_factory.cc +++ b/components/wifi_sync/wifi_credential_syncable_service_factory.cc
@@ -4,11 +4,44 @@ #include "components/wifi_sync/wifi_credential_syncable_service_factory.h" +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" #include "components/wifi_sync/wifi_credential_syncable_service.h" +#if defined(OS_CHROMEOS) +#include "chromeos/login/login_state.h" +#include "chromeos/network/network_handler.h" +#include "components/wifi_sync/wifi_config_delegate_chromeos.h" +#endif + namespace wifi_sync { +namespace { + +scoped_ptr<WifiConfigDelegate> BuildConfigDelegate( + content::BrowserContext* context) { +#if defined(OS_CHROMEOS) + const chromeos::LoginState* login_state = chromeos::LoginState::Get(); + DCHECK(login_state->IsUserLoggedIn()); + DCHECK(!login_state->primary_user_hash().empty()); + // TODO(quiche): Verify that |context| is the primary user's context. + + // Note: NetworkHandler is a singleton that is managed by + // ChromeBrowserMainPartsChromeos, and destroyed after all + // KeyedService instances are destroyed. + chromeos::NetworkHandler* network_handler = chromeos::NetworkHandler::Get(); + return make_scoped_ptr(new WifiConfigDelegateChromeOs( + login_state->primary_user_hash(), + network_handler->managed_network_configuration_handler())); +#else + NOTREACHED(); + return nullptr; +#endif +} + +} // namespace + // static WifiCredentialSyncableService* WifiCredentialSyncableServiceFactory::GetForBrowserContext( @@ -38,7 +71,7 @@ content::BrowserContext* context) const { // TODO(quiche): Figure out if this behaves properly for multi-profile. // crbug.com/430681. - return new WifiCredentialSyncableService(); + return new WifiCredentialSyncableService(BuildConfigDelegate(context)); } } // namespace wifi_sync
diff --git a/components/wifi_sync/wifi_credential_syncable_service_unittest.cc b/components/wifi_sync/wifi_credential_syncable_service_unittest.cc new file mode 100644 index 0000000..d5de955 --- /dev/null +++ b/components/wifi_sync/wifi_credential_syncable_service_unittest.cc
@@ -0,0 +1,286 @@ +// Copyright 2015 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/wifi_sync/wifi_credential_syncable_service.h" + +#include <string> +#include <vector> + +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "base/time/time.h" +#include "base/tracked_objects.h" +#include "components/wifi_sync/wifi_config_delegate.h" +#include "components/wifi_sync/wifi_credential.h" +#include "components/wifi_sync/wifi_security_class.h" +#include "sync/api/attachments/attachment_id.h" +#include "sync/api/fake_sync_change_processor.h" +#include "sync/api/sync_change.h" +#include "sync/api/sync_data.h" +#include "sync/api/sync_error.h" +#include "sync/api/sync_error_factory_mock.h" +#include "sync/internal_api/public/attachments/attachment_service_proxy_for_test.h" +#include "sync/protocol/sync.pb.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace wifi_sync { + +using syncer::FakeSyncChangeProcessor; +using syncer::SyncErrorFactoryMock; + +namespace { + +const char kSsidNonUtf8[] = "\xc0"; + +// Fake implementation of WifiConfigDelegate, which provides the +// ability to check how many times a WifiConfigDelegate method has +// been called. +class FakeWifiConfigDelegate : public WifiConfigDelegate { + public: + FakeWifiConfigDelegate() : add_count_(0) {} + ~FakeWifiConfigDelegate() override {} + + // WifiConfigDelegate implementation. + void AddToLocalNetworks(const WifiCredential& network_credential) override { + ++add_count_; + } + + // Returns the number of times the AddToLocalNetworks method has + // been called. + unsigned int add_count() const { return add_count_; } + + private: + // The number of times AddToLocalNetworks has been called on this fake. + unsigned int add_count_; + + DISALLOW_COPY_AND_ASSIGN(FakeWifiConfigDelegate); +}; + +// Unit tests for WifiCredentialSyncableService. +class WifiCredentialSyncableServiceTest : public testing::Test { + protected: + WifiCredentialSyncableServiceTest() + : config_delegate_(new FakeWifiConfigDelegate()), + change_processor_(nullptr) { + syncable_service_.reset( + new WifiCredentialSyncableService(make_scoped_ptr(config_delegate_))); + } + + // Wrappers for methods in WifiCredentialSyncableService. + syncer::SyncError ProcessSyncChanges( + const syncer::SyncChangeList& change_list) { + return syncable_service_->ProcessSyncChanges(FROM_HERE, change_list); + } + bool AddToSyncedNetworks(const std::string& item_id, + const WifiCredential& credential) { + return syncable_service_->AddToSyncedNetworks(item_id, credential); + } + + // Returns the number of change requests received by + // |change_processor_|. + int change_processor_changes_size() { + CHECK(change_processor_); + return change_processor_->changes().size(); + } + + // Returns the number of times AddToLocalNetworks has been called on + // |config_delegate_|. + unsigned int config_delegate_add_count() { + return config_delegate_->add_count(); + } + + // Returns a new WifiCredential constructed from the given parameters. + WifiCredential MakeCredential(const std::string& ssid, + WifiSecurityClass security_class, + const std::string& passphrase) { + scoped_ptr<WifiCredential> credential = WifiCredential::Create( + WifiCredential::MakeSsidBytesForTest(ssid), security_class, passphrase); + CHECK(credential); + return *credential; + } + + // Returns a new EntitySpecifics protobuf, with the + // wifi_credential_specifics fields populated with the given + // parameters. + sync_pb::EntitySpecifics MakeWifiCredentialSpecifics( + const std::string& ssid, + sync_pb::WifiCredentialSpecifics_SecurityClass security_class, + const std::string* passphrase) { + const std::vector<uint8_t> ssid_bytes(ssid.begin(), ssid.end()); + sync_pb::EntitySpecifics sync_entity_specifics; + sync_pb::WifiCredentialSpecifics* wifi_credential_specifics = + sync_entity_specifics.mutable_wifi_credential(); + CHECK(wifi_credential_specifics); + wifi_credential_specifics->set_ssid(ssid_bytes.data(), ssid_bytes.size()); + wifi_credential_specifics->set_security_class(security_class); + if (passphrase) { + wifi_credential_specifics->set_passphrase(passphrase->data(), + passphrase->size()); + } + return sync_entity_specifics; + } + + syncer::SyncChange MakeActionAdd( + int sync_item_id, + const std::string& ssid, + sync_pb::WifiCredentialSpecifics_SecurityClass security_class, + const std::string* passphrase) { + return syncer::SyncChange( + FROM_HERE, syncer::SyncChange::ACTION_ADD, + syncer::SyncData::CreateRemoteData( + sync_item_id, + MakeWifiCredentialSpecifics(ssid, security_class, passphrase), + base::Time(), syncer::AttachmentIdList(), + syncer::AttachmentServiceProxyForTest::Create())); + } + + void StartSyncing() { + scoped_ptr<FakeSyncChangeProcessor> change_processor( + new FakeSyncChangeProcessor()); + change_processor_ = change_processor.get(); + syncable_service_->MergeDataAndStartSyncing( + syncer::WIFI_CREDENTIALS, syncer::SyncDataList(), + change_processor.Pass(), make_scoped_ptr(new SyncErrorFactoryMock())); + } + + private: + scoped_ptr<WifiCredentialSyncableService> syncable_service_; + FakeWifiConfigDelegate* config_delegate_; // Owned by |syncable_service_| + FakeSyncChangeProcessor* change_processor_; // Owned by |syncable_service_| + + DISALLOW_COPY_AND_ASSIGN(WifiCredentialSyncableServiceTest); +}; + +} // namespace + +TEST_F(WifiCredentialSyncableServiceTest, ProcessSyncChangesNotStarted) { + syncer::SyncError sync_error(ProcessSyncChanges(syncer::SyncChangeList())); + ASSERT_TRUE(sync_error.IsSet()); + EXPECT_EQ(syncer::SyncError::UNREADY_ERROR, sync_error.error_type()); + EXPECT_EQ(0U, config_delegate_add_count()); +} + +TEST_F(WifiCredentialSyncableServiceTest, + ProcessSyncChangesActionAddSecurityClassInvalid) { + syncer::SyncChangeList changes; + const int sync_item_id = 1; + changes.push_back(MakeActionAdd( + sync_item_id, kSsidNonUtf8, + sync_pb::WifiCredentialSpecifics::SECURITY_CLASS_INVALID, nullptr)); + StartSyncing(); + syncer::SyncError sync_error = ProcessSyncChanges(changes); + EXPECT_FALSE(sync_error.IsSet()); // Bad items are ignored. + EXPECT_EQ(0U, config_delegate_add_count()); +} + +TEST_F(WifiCredentialSyncableServiceTest, + ProcessSyncChangesActionAddSecurityClassNoneSuccess) { + syncer::SyncChangeList changes; + const int sync_item_id = 1; + changes.push_back(MakeActionAdd( + sync_item_id, kSsidNonUtf8, + sync_pb::WifiCredentialSpecifics::SECURITY_CLASS_NONE, nullptr)); + StartSyncing(); + syncer::SyncError sync_error = ProcessSyncChanges(changes); + EXPECT_FALSE(sync_error.IsSet()); + EXPECT_EQ(1U, config_delegate_add_count()); +} + +TEST_F(WifiCredentialSyncableServiceTest, + ProcessSyncChangesActionAddSecurityClassWepMissingPassphrase) { + syncer::SyncChangeList changes; + const int sync_item_id = 1; + changes.push_back(MakeActionAdd( + sync_item_id, kSsidNonUtf8, + sync_pb::WifiCredentialSpecifics::SECURITY_CLASS_WEP, nullptr)); + StartSyncing(); + syncer::SyncError sync_error = ProcessSyncChanges(changes); + EXPECT_FALSE(sync_error.IsSet()); // Bad items are ignored. + EXPECT_EQ(0U, config_delegate_add_count()); +} + +TEST_F(WifiCredentialSyncableServiceTest, + ProcessSyncChangesActionAddSecurityClassWepSuccess) { + syncer::SyncChangeList changes; + const int sync_item_id = 1; + const std::string passphrase("abcde"); + changes.push_back(MakeActionAdd( + sync_item_id, kSsidNonUtf8, + sync_pb::WifiCredentialSpecifics::SECURITY_CLASS_WEP, &passphrase)); + StartSyncing(); + syncer::SyncError sync_error = ProcessSyncChanges(changes); + EXPECT_FALSE(sync_error.IsSet()); + EXPECT_EQ(1U, config_delegate_add_count()); +} + +TEST_F(WifiCredentialSyncableServiceTest, + ProcessSyncChangesActionAddSecurityClassPskMissingPassphrase) { + syncer::SyncChangeList changes; + const int sync_item_id = 1; + changes.push_back(MakeActionAdd( + sync_item_id, kSsidNonUtf8, + sync_pb::WifiCredentialSpecifics::SECURITY_CLASS_PSK, nullptr)); + StartSyncing(); + syncer::SyncError sync_error = ProcessSyncChanges(changes); + EXPECT_FALSE(sync_error.IsSet()); // Bad items are ignored. + EXPECT_EQ(0U, config_delegate_add_count()); +} + +TEST_F(WifiCredentialSyncableServiceTest, + ProcessSyncChangesActionAddSecurityClassPskSuccess) { + syncer::SyncChangeList changes; + const int sync_item_id = 1; + const std::string passphrase("psk-passphrase"); + changes.push_back(MakeActionAdd( + sync_item_id, kSsidNonUtf8, + sync_pb::WifiCredentialSpecifics::SECURITY_CLASS_PSK, &passphrase)); + StartSyncing(); + syncer::SyncError sync_error = ProcessSyncChanges(changes); + EXPECT_FALSE(sync_error.IsSet()); + EXPECT_EQ(1U, config_delegate_add_count()); +} + +TEST_F(WifiCredentialSyncableServiceTest, + ProcessSyncChangesContinuesAfterSecurityClassInvalid) { + syncer::SyncChangeList changes; + changes.push_back(MakeActionAdd( + 1 /* sync item id */, kSsidNonUtf8, + sync_pb::WifiCredentialSpecifics::SECURITY_CLASS_INVALID, nullptr)); + changes.push_back(MakeActionAdd( + 2 /* sync item id */, kSsidNonUtf8, + sync_pb::WifiCredentialSpecifics::SECURITY_CLASS_NONE, nullptr)); + StartSyncing(); + syncer::SyncError sync_error = ProcessSyncChanges(changes); + EXPECT_FALSE(sync_error.IsSet()); // Bad items are ignored. + EXPECT_EQ(1U, config_delegate_add_count()); +} + +TEST_F(WifiCredentialSyncableServiceTest, + ProcessSyncChangesContinuesAfterMissingPassphrase) { + syncer::SyncChangeList changes; + changes.push_back(MakeActionAdd( + 1 /* sync item id */, kSsidNonUtf8, + sync_pb::WifiCredentialSpecifics::SECURITY_CLASS_WEP, nullptr)); + changes.push_back(MakeActionAdd( + 2 /* sync item id */, kSsidNonUtf8, + sync_pb::WifiCredentialSpecifics::SECURITY_CLASS_NONE, nullptr)); + StartSyncing(); + syncer::SyncError sync_error = ProcessSyncChanges(changes); + EXPECT_FALSE(sync_error.IsSet()); // Bad items are ignored. + EXPECT_EQ(1U, config_delegate_add_count()); +} + +TEST_F(WifiCredentialSyncableServiceTest, AddToSyncedNetworksNotStarted) { + EXPECT_FALSE(AddToSyncedNetworks( + "fake-item-id", MakeCredential(kSsidNonUtf8, SECURITY_CLASS_NONE, ""))); +} + +TEST_F(WifiCredentialSyncableServiceTest, AddToSyncedNetworksSuccess) { + StartSyncing(); + EXPECT_TRUE(AddToSyncedNetworks( + "fake-item-id", MakeCredential(kSsidNonUtf8, SECURITY_CLASS_NONE, ""))); + EXPECT_EQ(1, change_processor_changes_size()); +} + +} // namespace wifi_sync
diff --git a/content/DEPS b/content/DEPS index fadf694..fb2bf9d 100644 --- a/content/DEPS +++ b/content/DEPS
@@ -33,10 +33,6 @@ "+dbus", "+gpu", "+mojo/common", - "+mojo/edk/embedder", - "+mojo/edk/js", - "+mojo/edk/test", - "+mojo/public", "+net", "+ppapi", "+printing", @@ -63,6 +59,10 @@ "+third_party/angle", "+third_party/flac", "+third_party/libjingle", + "+third_party/mojo/src/mojo/edk/embedder", + "+third_party/mojo/src/mojo/edk/js", + "+third_party/mojo/src/mojo/edk/test", + "+third_party/mojo/src/mojo/public", "+third_party/mozilla", "+third_party/npapi/bindings", "+third_party/re2",
diff --git a/content/app/mojo/mojo_browsertest.cc b/content/app/mojo/mojo_browsertest.cc index b516107..c7f179cd 100644 --- a/content/app/mojo/mojo_browsertest.cc +++ b/content/app/mojo/mojo_browsertest.cc
@@ -3,8 +3,8 @@ // found in the LICENSE file. #include "content/public/test/content_browser_test.h" -#include "mojo/public/c/system/core.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/mojo/src/mojo/public/c/system/core.h" namespace content {
diff --git a/content/app/mojo/mojo_init.cc b/content/app/mojo/mojo_init.cc index 3b08791..c706255 100644 --- a/content/app/mojo/mojo_init.cc +++ b/content/app/mojo/mojo_init.cc
@@ -4,21 +4,32 @@ #include "content/app/mojo/mojo_init.h" +#include "base/lazy_instance.h" #include "base/memory/scoped_ptr.h" -#include "mojo/edk/embedder/configuration.h" -#include "mojo/edk/embedder/embedder.h" -#include "mojo/edk/embedder/simple_platform_support.h" +#include "third_party/mojo/src/mojo/edk/embedder/configuration.h" +#include "third_party/mojo/src/mojo/edk/embedder/embedder.h" +#include "third_party/mojo/src/mojo/edk/embedder/simple_platform_support.h" namespace content { +namespace { + +class MojoInitializer { + public: + MojoInitializer() { + mojo::embedder::GetConfiguration()->max_message_num_bytes = + 64 * 1024 * 1024; + mojo::embedder::Init(scoped_ptr<mojo::embedder::PlatformSupport>( + new mojo::embedder::SimplePlatformSupport())); + } +}; + +base::LazyInstance<MojoInitializer>::Leaky mojo_initializer; + +} // namespace + void InitializeMojo() { - // Things like content_shell and DevTools ocassionally send big - // message which includes whole rendered screen or all loaded - // scripts. The buffer size has to be big enough to allow such use - // cases. - mojo::embedder::GetConfiguration()->max_message_num_bytes = 64*1024*1024; - mojo::embedder::Init(scoped_ptr<mojo::embedder::PlatformSupport>( - new mojo::embedder::SimplePlatformSupport())); + mojo_initializer.Get(); } } // namespace content
diff --git a/content/app/startup_helper_win.cc b/content/app/startup_helper_win.cc index ab85a43..e19630fe 100644 --- a/content/app/startup_helper_win.cc +++ b/content/app/startup_helper_win.cc
@@ -43,7 +43,8 @@ // Ensure the proper mitigations are enforced for the browser process. sandbox::ApplyProcessMitigationsToCurrentProcess( sandbox::MITIGATION_DEP | - sandbox::MITIGATION_DEP_NO_ATL_THUNK); + sandbox::MITIGATION_DEP_NO_ATL_THUNK | + sandbox::MITIGATION_HARDEN_TOKEN_IL_POLICY); } }
diff --git a/content/browser/accessibility/browser_accessibility.cc b/content/browser/accessibility/browser_accessibility.cc index 8cc30d13..65d805b 100644 --- a/content/browser/accessibility/browser_accessibility.cc +++ b/content/browser/accessibility/browser_accessibility.cc
@@ -38,11 +38,6 @@ node_ = node; } -void BrowserAccessibility::OnDataChanged() { - GetStringAttribute(ui::AX_ATTR_NAME, &name_); - GetStringAttribute(ui::AX_ATTR_VALUE, &value_); -} - bool BrowserAccessibility::PlatformIsLeaf() const { if (InternalChildCount() == 0) return true; @@ -96,6 +91,17 @@ return result; } +bool BrowserAccessibility::PlatformIsChildOfLeaf() const { + BrowserAccessibility* ancestor = GetParent(); + while (ancestor) { + if (ancestor->PlatformIsLeaf()) + return true; + ancestor = ancestor->GetParent(); + } + + return false; +} + BrowserAccessibility* BrowserAccessibility::GetPreviousSibling() { if (GetParent() && GetIndexInParent() > 0) return GetParent()->InternalGetChild(GetIndexInParent() - 1); @@ -384,9 +390,6 @@ void BrowserAccessibility::Destroy() { // Allow the object to fire a TextRemoved notification. - name_.clear(); - value_.clear(); - manager_->NotifyAccessibilityEvent(ui::AX_EVENT_HIDE, this); node_ = NULL; manager_ = NULL; @@ -557,24 +560,6 @@ return true; } -void BrowserAccessibility::SetStringAttribute( - ui::AXStringAttribute attribute, const std::string& value) { - if (!node_) - return; - ui::AXNodeData data = GetData(); - for (size_t i = 0; i < data.string_attributes.size(); ++i) { - if (data.string_attributes[i].first == attribute) { - data.string_attributes[i].second = value; - node_->SetData(data); - return; - } - } - if (!value.empty()) { - data.string_attributes.push_back(std::make_pair(attribute, value)); - node_->SetData(data); - } -} - bool BrowserAccessibility::HasIntListAttribute( ui::AXIntListAttribute attribute) const { const ui::AXNodeData& data = GetData(); @@ -702,17 +687,6 @@ return grandparent->GetRole() == ui::AX_ROLE_IFRAME_PRESENTATIONAL; } -std::string BrowserAccessibility::GetTextRecursive() const { - if (!name_.empty()) { - return name_; - } - - std::string result; - for (uint32 i = 0; i < PlatformChildCount(); ++i) - result += PlatformGetChild(i)->GetTextRecursive(); - return result; -} - int BrowserAccessibility::GetStaticTextLenRecursive() const { if (GetRole() == ui::AX_ROLE_STATIC_TEXT) return static_cast<int>(GetStringAttribute(ui::AX_ATTR_VALUE).size());
diff --git a/content/browser/accessibility/browser_accessibility.h b/content/browser/accessibility/browser_accessibility.h index 37f2fe04..e8a7d387 100644 --- a/content/browser/accessibility/browser_accessibility.h +++ b/content/browser/accessibility/browser_accessibility.h
@@ -56,15 +56,15 @@ // Called after the object is first initialized and again every time // its data changes. - virtual void OnDataChanged(); + virtual void OnDataChanged() {} // Called after an atomic update to the tree finished and this object // was created or changed in this update. virtual void OnUpdateFinished() {} - // Returns true if this is a native platform-specific object, vs a - // cross-platform generic object. - virtual bool IsNative() const; + virtual void OnSubtreeWillBeDeleted() {} + + virtual void OnSubtreeCreationFinished() {} // Called when the location changed. virtual void OnLocationChanged() {} @@ -88,6 +88,11 @@ // invalid index. Returns NULL if PlatformIsLeaf() returns true. BrowserAccessibility* PlatformGetChild(uint32 child_index) const; + // Returns true if an ancestor of this node (not including itself) is a + // leaf node, meaning that this node is not actually exposed to the + // platform. + bool PlatformIsChildOfLeaf() const; + // Return the previous sibling of this object, or NULL if it's the first // child of its parent. BrowserAccessibility* GetPreviousSibling(); @@ -140,10 +145,6 @@ BrowserAccessibilityManager* manager() const { return manager_; } bool instance_active() const { return node_ != NULL; } ui::AXNode* node() const { return node_; } - const std::string& name() const { return name_; } - const std::string& value() const { return value_; } - void set_name(const std::string& name) { name_ = name; } - void set_value(const std::string& value) { value_ = value; } // These access the internal accessibility tree, which doesn't necessarily // reflect the accessibility tree that should be exposed on each platform. @@ -164,6 +165,12 @@ typedef base::StringPairs HtmlAttributes; const HtmlAttributes& GetHtmlAttributes() const; + + // Returns true if this is a native platform-specific object, vs a + // cross-platform generic object. Don't call ToBrowserAccessibilityXXX if + // IsNative returns false. + virtual bool IsNative() const; + #if defined(OS_MACOSX) && __OBJC__ BrowserAccessibilityCocoa* ToBrowserAccessibilityCocoa(); #elif defined(OS_WIN) @@ -214,9 +221,6 @@ bool GetIntListAttribute(ui::AXIntListAttribute attribute, std::vector<int32>* value) const; - void SetStringAttribute(ui::AXStringAttribute attribute, - const std::string& value); - // Retrieve the value of a html attribute from the attribute map and // returns true if found. bool GetHtmlAttribute(const char* attr, base::string16* value) const; @@ -250,9 +254,6 @@ // True if this is a web area, and its grandparent is a presentational iframe. bool IsWebAreaForPresentationalIframe() const; - // Append the text from this node and its children. - std::string GetTextRecursive() const; - protected: BrowserAccessibility(); @@ -272,9 +273,6 @@ // bounds offsets. BrowserAccessibility* GetParentForBoundsCalculation() const; - std::string name_; - std::string value_; - DISALLOW_COPY_AND_ASSIGN(BrowserAccessibility); };
diff --git a/content/browser/accessibility/browser_accessibility_android.cc b/content/browser/accessibility/browser_accessibility_android.cc index 8ea3c563..532a40d 100644 --- a/content/browser/accessibility/browser_accessibility_android.cc +++ b/content/browser/accessibility/browser_accessibility_android.cc
@@ -330,16 +330,17 @@ // First, always return the |value| attribute if this is an // input field. - if (!value().empty()) { + base::string16 value = GetString16Attribute(ui::AX_ATTR_VALUE); + if (!value.empty()) { if (HasState(ui::AX_STATE_EDITABLE)) - return base::UTF8ToUTF16(value()); + return value; switch (GetRole()) { case ui::AX_ROLE_COMBO_BOX: case ui::AX_ROLE_POP_UP_BUTTON: case ui::AX_ROLE_TEXT_AREA: case ui::AX_ROLE_TEXT_FIELD: - return base::UTF8ToUTF16(value()); + return value; } } @@ -356,8 +357,9 @@ // Always prefer visible text if this is a link. Sites sometimes add // a "title" attribute to a link with more information, but we can't // lose the link text. - if (!name().empty() && GetRole() == ui::AX_ROLE_LINK) - return base::UTF8ToUTF16(name()); + base::string16 name = GetString16Attribute(ui::AX_ATTR_NAME); + if (!name.empty() && GetRole() == ui::AX_ROLE_LINK) + return name; // If there's no text value, the basic rule is: prefer description // (aria-labelledby or aria-label), then help (title), then name @@ -383,16 +385,16 @@ base::string16 text; if (!description.empty()) text = description; - else if (title_elem_id && !name().empty()) - text = base::UTF8ToUTF16(name()); + else if (title_elem_id && !name.empty()) + text = name; else if (!help.empty()) text = help; - else if (!name().empty()) - text = base::UTF8ToUTF16(name()); + else if (!name.empty()) + text = name; else if (!placeholder.empty()) text = placeholder; - else if (!value().empty()) - text = base::UTF8ToUTF16(value()); + else if (!value.empty()) + text = value; else if (title_elem_id) { BrowserAccessibility* title_elem = manager()->GetFromID(title_elem_id); @@ -563,7 +565,8 @@ } int BrowserAccessibilityAndroid::GetEditableTextLength() const { - return value().length(); + base::string16 value = GetString16Attribute(ui::AX_ATTR_VALUE); + return value.length(); } int BrowserAccessibilityAndroid::AndroidInputType() const { @@ -831,9 +834,10 @@ BrowserAccessibility::OnDataChanged(); if (IsEditableText()) { - if (base::UTF8ToUTF16(value()) != new_value_) { + base::string16 value = GetString16Attribute(ui::AX_ATTR_VALUE); + if (value != new_value_) { old_value_ = new_value_; - new_value_ = base::UTF8ToUTF16(value()); + new_value_ = value; } }
diff --git a/content/browser/accessibility/browser_accessibility_cocoa.mm b/content/browser/accessibility/browser_accessibility_cocoa.mm index dd3daeb..b6f58df 100644 --- a/content/browser/accessibility/browser_accessibility_cocoa.mm +++ b/content/browser/accessibility/browser_accessibility_cocoa.mm
@@ -482,7 +482,9 @@ } - (NSNumber*)numberOfCharacters { - return [NSNumber numberWithInt:browserAccessibility_->value().length()]; + std::string value = browserAccessibility_->GetStringAttribute( + ui::AX_ATTR_VALUE); + return [NSNumber numberWithInt:value.size()]; } // The origin of this accessibility object in the page's document. @@ -918,8 +920,9 @@ } - (NSValue*)visibleCharacterRange { - return [NSValue valueWithRange: - NSMakeRange(0, browserAccessibility_->value().length())]; + std::string value = browserAccessibility_->GetStringAttribute( + ui::AX_ATTR_VALUE); + return [NSValue valueWithRange:NSMakeRange(0, value.size())]; } - (NSArray*)visibleCells { @@ -1033,7 +1036,9 @@ const std::vector<int32>& line_breaks = browserAccessibility_->GetIntListAttribute( ui::AX_ATTR_LINE_BREAKS); - int len = static_cast<int>(browserAccessibility_->value().size()); + std::string value = browserAccessibility_->GetStringAttribute( + ui::AX_ATTR_VALUE); + int len = static_cast<int>(value.size()); if ([attribute isEqualToString: NSAccessibilityStringForRangeParameterizedAttribute]) {
diff --git a/content/browser/accessibility/browser_accessibility_manager.cc b/content/browser/accessibility/browser_accessibility_manager.cc index 7e726bd..781eadd 100644 --- a/content/browser/accessibility/browser_accessibility_manager.cc +++ b/content/browser/accessibility/browser_accessibility_manager.cc
@@ -185,8 +185,6 @@ } } - OnTreeUpdateFinished(); - if (should_send_initial_focus && (!delegate_ || delegate_->AccessibilityViewHasFocus())) { NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, GetFromAXNode(focus_)); @@ -415,6 +413,12 @@ id_wrapper_map_.erase(node->id()); } +void BrowserAccessibilityManager::OnSubtreeWillBeDeleted(ui::AXNode* node) { + BrowserAccessibility* obj = GetFromAXNode(node); + if (obj) + obj->OnSubtreeWillBeDeleted(); +} + void BrowserAccessibilityManager::OnNodeCreated(ui::AXNode* node) { BrowserAccessibility* wrapper = factory_->Create(); wrapper->Init(this, node); @@ -426,12 +430,18 @@ GetFromAXNode(node)->OnDataChanged(); } -void BrowserAccessibilityManager::OnNodeCreationFinished(ui::AXNode* node) { - GetFromAXNode(node)->OnUpdateFinished(); -} +void BrowserAccessibilityManager::OnAtomicUpdateFinished( + bool root_changed, + const std::vector<ui::AXTreeDelegate::Change>& changes) { + for (size_t i = 0; i < changes.size(); ++i) { + BrowserAccessibility* obj = GetFromAXNode(changes[i].node); + if (!obj) + continue; -void BrowserAccessibilityManager::OnNodeChangeFinished(ui::AXNode* node) { - GetFromAXNode(node)->OnUpdateFinished(); + obj->OnUpdateFinished(); + if (changes[i].type == AXTreeDelegate::SUBTREE_CREATED) + GetFromAXNode(changes[i].node)->OnSubtreeCreationFinished(); + } } BrowserAccessibilityDelegate*
diff --git a/content/browser/accessibility/browser_accessibility_manager.h b/content/browser/accessibility/browser_accessibility_manager.h index 765ac4d9..e59a1ed 100644 --- a/content/browser/accessibility/browser_accessibility_manager.h +++ b/content/browser/accessibility/browser_accessibility_manager.h
@@ -235,11 +235,12 @@ // AXTreeDelegate implementation. void OnNodeWillBeDeleted(ui::AXNode* node) override; + void OnSubtreeWillBeDeleted(ui::AXNode* node) override; void OnNodeCreated(ui::AXNode* node) override; void OnNodeChanged(ui::AXNode* node) override; - void OnNodeCreationFinished(ui::AXNode* node) override; - void OnNodeChangeFinished(ui::AXNode* node) override; - void OnRootChanged(ui::AXNode* new_root) override {} + void OnAtomicUpdateFinished( + bool root_changed, + const std::vector<ui::AXTreeDelegate::Change>& changes) override; BrowserAccessibilityDelegate* delegate() const { return delegate_; } void set_delegate(BrowserAccessibilityDelegate* delegate) { @@ -264,9 +265,6 @@ BrowserAccessibilityDelegate* delegate, BrowserAccessibilityFactory* factory); - // Called at the end of updating the tree. - virtual void OnTreeUpdateFinished() {} - private: // The following states keep track of whether or not the // on-screen keyboard is allowed to be shown.
diff --git a/content/browser/accessibility/browser_accessibility_manager_android.cc b/content/browser/accessibility/browser_accessibility_manager_android.cc index fd4e0ff..ef7cd01e 100644 --- a/content/browser/accessibility/browser_accessibility_manager_android.cc +++ b/content/browser/accessibility/browser_accessibility_manager_android.cc
@@ -724,13 +724,17 @@ delegate_->AccessibilitySetAccessibilityFocus(id); } -void BrowserAccessibilityManagerAndroid::OnRootChanged(ui::AXNode* new_root) { - JNIEnv* env = AttachCurrentThread(); - ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); - if (obj.is_null()) - return; +void BrowserAccessibilityManagerAndroid::OnAtomicUpdateFinished( + bool root_changed, + const std::vector<ui::AXTreeDelegate::Change>& changes) { + if (root_changed) { + JNIEnv* env = AttachCurrentThread(); + ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); + if (obj.is_null()) + return; - Java_BrowserAccessibilityManager_handleNavigate(env, obj.obj()); + Java_BrowserAccessibilityManager_handleNavigate(env, obj.obj()); + } } bool
diff --git a/content/browser/accessibility/browser_accessibility_manager_android.h b/content/browser/accessibility/browser_accessibility_manager_android.h index f0e2d344..3d96d5d4 100644 --- a/content/browser/accessibility/browser_accessibility_manager_android.h +++ b/content/browser/accessibility/browser_accessibility_manager_android.h
@@ -123,7 +123,9 @@ protected: // AXTreeDelegate overrides. - virtual void OnRootChanged(ui::AXNode* new_root) override; + void OnAtomicUpdateFinished( + bool root_changed, + const std::vector<ui::AXTreeDelegate::Change>& changes) override; virtual bool UseRootScrollOffsetsWhenComputingBounds() override;
diff --git a/content/browser/accessibility/browser_accessibility_manager_mac.h b/content/browser/accessibility/browser_accessibility_manager_mac.h index b754a4b..02115e8 100644 --- a/content/browser/accessibility/browser_accessibility_manager_mac.h +++ b/content/browser/accessibility/browser_accessibility_manager_mac.h
@@ -31,8 +31,9 @@ NSView* parent_view() { return parent_view_; } private: - void OnNodeCreationFinished(ui::AXNode* node) override; - void OnTreeUpdateFinished() override; + void OnAtomicUpdateFinished( + bool root_changed, + const std::vector<ui::AXTreeDelegate::Change>& changes) override; // This gives BrowserAccessibilityManager::Create access to the class // constructor. @@ -40,8 +41,6 @@ NSView* parent_view_; - bool created_live_region_; - DISALLOW_COPY_AND_ASSIGN(BrowserAccessibilityManagerMac); };
diff --git a/content/browser/accessibility/browser_accessibility_manager_mac.mm b/content/browser/accessibility/browser_accessibility_manager_mac.mm index 2000d025..ab92723 100644 --- a/content/browser/accessibility/browser_accessibility_manager_mac.mm +++ b/content/browser/accessibility/browser_accessibility_manager_mac.mm
@@ -26,8 +26,7 @@ BrowserAccessibilityDelegate* delegate, BrowserAccessibilityFactory* factory) : BrowserAccessibilityManager(delegate, factory), - parent_view_(parent_view), - created_live_region_(false) { + parent_view_(parent_view) { Initialize(initial_tree); } @@ -145,14 +144,20 @@ NSAccessibilityPostNotification(native_node, event_id); } -void BrowserAccessibilityManagerMac::OnNodeCreationFinished(ui::AXNode* node) { - BrowserAccessibility* obj = GetFromAXNode(node); - if (obj && obj->HasStringAttribute(ui::AX_ATTR_LIVE_STATUS)) - created_live_region_ = true; -} +void BrowserAccessibilityManagerMac::OnAtomicUpdateFinished( + bool root_changed, const std::vector<ui::AXTreeDelegate::Change>& changes) { + BrowserAccessibilityManager::OnAtomicUpdateFinished(root_changed, changes); -void BrowserAccessibilityManagerMac::OnTreeUpdateFinished() { - if (!created_live_region_) + bool created_live_region = false; + for (size_t i = 0; i < changes.size(); ++i) { + BrowserAccessibility* obj = GetFromAXNode(changes[i].node); + if (obj && obj->HasStringAttribute(ui::AX_ATTR_LIVE_STATUS)) { + created_live_region = true; + break; + } + } + + if (!created_live_region) return; // This code is to work around a bug in VoiceOver, where a new live @@ -164,8 +169,6 @@ static_cast<BrowserAccessibilityMac*>(GetRoot()); root->RecreateNativeObject(); NotifyAccessibilityEvent(ui::AX_EVENT_CHILDREN_CHANGED, root); - - created_live_region_ = false; } } // namespace content
diff --git a/content/browser/accessibility/browser_accessibility_manager_win.cc b/content/browser/accessibility/browser_accessibility_manager_win.cc index d3449df..05ef1b1 100644 --- a/content/browser/accessibility/browser_accessibility_manager_win.cc +++ b/content/browser/accessibility/browser_accessibility_manager_win.cc
@@ -73,22 +73,66 @@ return delegate_->AccessibilityGetNativeViewAccessible(); } -void BrowserAccessibilityManagerWin::MaybeCallNotifyWinEvent(DWORD event, - LONG child_id) { +void BrowserAccessibilityManagerWin::MaybeCallNotifyWinEvent( + DWORD event, BrowserAccessibility* node) { BrowserAccessibilityDelegate* delegate = GetDelegateFromRootManager(); if (!delegate) return; + if (!node->IsNative()) + return; + HWND hwnd = delegate->AccessibilityGetAcceleratedWidget(); if (!hwnd) return; + // Inline text boxes are an internal implementation detail, we don't + // expose them to Windows. + if (node->GetRole() == ui::AX_ROLE_INLINE_TEXT_BOX) + return; + + // It doesn't make sense to fire a REORDER event on a leaf node; that + // happens when the node has internal children line inline text boxes. + if (event == EVENT_OBJECT_REORDER && node->PlatformIsLeaf()) + return; + + // Don't fire focus, or load complete notifications if the + // window isn't focused, because that can confuse screen readers into + // entering their "browse" mode. + if ((event == EVENT_OBJECT_FOCUS || + event == IA2_EVENT_DOCUMENT_LOAD_COMPLETE) && + (!delegate_->AccessibilityViewHasFocus())) { + return; + } + + // NVDA gets confused if we focus the main document element when it hasn't + // finished loading and it has no children at all, so suppress that event. + if (event == EVENT_OBJECT_FOCUS && + node == GetRoot() && + node->PlatformChildCount() == 0 && + !node->HasState(ui::AX_STATE_BUSY) && + !node->GetBoolAttribute(ui::AX_ATTR_DOC_LOADED)) { + return; + } + + // If a focus event is needed on the root, fire that first before + // this event. + if (event == EVENT_OBJECT_FOCUS && node == GetRoot()) + focus_event_on_root_needed_ = false; + else if (focus_event_on_root_needed_) + OnWindowFocused(); + + LONG child_id = node->ToBrowserAccessibilityWin()->unique_id_win(); ::NotifyWinEvent(event, hwnd, OBJID_CLIENT, child_id); } void BrowserAccessibilityManagerWin::OnNodeCreated(ui::AXNode* node) { BrowserAccessibilityManager::OnNodeCreated(node); BrowserAccessibility* obj = GetFromAXNode(node); + if (!obj) + return; + if (!obj->IsNative()) + return; LONG unique_id_win = obj->ToBrowserAccessibilityWin()->unique_id_win(); unique_id_to_ax_id_map_[unique_id_win] = obj->GetId(); } @@ -98,6 +142,8 @@ BrowserAccessibility* obj = GetFromAXNode(node); if (!obj) return; + if (!obj->IsNative()) + return; unique_id_to_ax_id_map_.erase( obj->ToBrowserAccessibilityWin()->unique_id_win()); if (obj == tracked_scroll_object_) { @@ -173,9 +219,6 @@ case ui::AX_EVENT_ALERT: event_id = EVENT_SYSTEM_ALERT; break; - case ui::AX_EVENT_ARIA_ATTRIBUTE_CHANGED: - event_id = IA2_EVENT_OBJECT_ATTRIBUTE_CHANGED; - break; case ui::AX_EVENT_AUTOCORRECTION_OCCURED: event_id = IA2_EVENT_OBJECT_ATTRIBUTE_CHANGED; break; @@ -184,18 +227,12 @@ event_id = EVENT_OBJECT_FOCUS; node = GetRoot(); break; - case ui::AX_EVENT_CHECKED_STATE_CHANGED: - event_id = EVENT_OBJECT_STATECHANGE; - break; case ui::AX_EVENT_CHILDREN_CHANGED: event_id = EVENT_OBJECT_REORDER; break; case ui::AX_EVENT_FOCUS: event_id = EVENT_OBJECT_FOCUS; break; - case ui::AX_EVENT_INVALID_STATUS_CHANGED: - event_id = EVENT_OBJECT_STATECHANGE; - break; case ui::AX_EVENT_LIVE_REGION_CHANGED: if (node->GetBoolAttribute(ui::AX_ATTR_CONTAINER_LIVE_BUSY)) return; @@ -210,12 +247,6 @@ case ui::AX_EVENT_MENU_LIST_VALUE_CHANGED: event_id = EVENT_OBJECT_VALUECHANGE; break; - case ui::AX_EVENT_HIDE: - event_id = EVENT_OBJECT_HIDE; - break; - case ui::AX_EVENT_SHOW: - event_id = EVENT_OBJECT_SHOW; - break; case ui::AX_EVENT_SCROLL_POSITION_CHANGED: event_id = EVENT_SYSTEM_SCROLLINGEND; break; @@ -225,15 +256,9 @@ case ui::AX_EVENT_SELECTED_CHILDREN_CHANGED: event_id = EVENT_OBJECT_SELECTIONWITHIN; break; - case ui::AX_EVENT_TEXT_CHANGED: - event_id = EVENT_OBJECT_NAMECHANGE; - break; case ui::AX_EVENT_TEXT_SELECTION_CHANGED: event_id = IA2_EVENT_TEXT_CARET_MOVED; break; - case ui::AX_EVENT_VALUE_CHANGED: - event_id = EVENT_OBJECT_VALUECHANGE; - break; default: // Not all WebKit accessibility events result in a Windows // accessibility notification. @@ -245,8 +270,7 @@ // the AT client will then call get_accChild on the HWND's accessibility // object and pass it that same id, which we can use to retrieve the // IAccessible for this node. - LONG child_id = node->ToBrowserAccessibilityWin()->unique_id_win(); - MaybeCallNotifyWinEvent(event_id, child_id); + MaybeCallNotifyWinEvent(event_id, node); } // If this is a layout complete notification (sent when a container scrolls) @@ -256,17 +280,35 @@ tracked_scroll_object_ && tracked_scroll_object_->IsDescendantOf(node)) { MaybeCallNotifyWinEvent( - IA2_EVENT_VISIBLE_DATA_CHANGED, - tracked_scroll_object_->ToBrowserAccessibilityWin()->unique_id_win()); + IA2_EVENT_VISIBLE_DATA_CHANGED, tracked_scroll_object_); tracked_scroll_object_->Release(); tracked_scroll_object_ = NULL; } } -void BrowserAccessibilityManagerWin::OnRootChanged(ui::AXNode* new_root) { - // In order to make screen readers aware of the new accessibility root, - // we need to fire a focus event on it. - OnWindowFocused(); +void BrowserAccessibilityManagerWin::OnAtomicUpdateFinished( + bool root_changed, + const std::vector<ui::AXTreeDelegate::Change>& changes) { + BrowserAccessibilityManager::OnAtomicUpdateFinished(root_changed, changes); + + if (root_changed) { + // In order to make screen readers aware of the new accessibility root, + // we need to fire a focus event on it. + OnWindowFocused(); + } + + // BrowserAccessibilityManager::OnAtomicUpdateFinished calls + // OnUpdateFinished() on each node in |changes|. However, the + // IAccessibleText text for a node is a concatenatenation of all of its child + // text nodes, so we can't compute a node's IAccessibleText in + // OnUpdateFinished because its children may not have been updated yet. + // + // So we make a second pass here to update IAccessibleText. + for (size_t i = 0; i < changes.size(); ++i) { + BrowserAccessibility* obj = GetFromAXNode(changes[i].node); + if (obj && obj->IsNative()) + obj->ToBrowserAccessibilityWin()->UpdateIAccessibleText(); + } } void BrowserAccessibilityManagerWin::TrackScrollingObject( @@ -283,7 +325,7 @@ unique_id_to_ax_id_map_.find(unique_id_win); if (iter != unique_id_to_ax_id_map_.end()) { BrowserAccessibility* result = GetFromID(iter->second); - if (result) + if (result && result->IsNative()) return result->ToBrowserAccessibilityWin(); }
diff --git a/content/browser/accessibility/browser_accessibility_manager_win.h b/content/browser/accessibility/browser_accessibility_manager_win.h index 8eaa949..7f0039e 100644 --- a/content/browser/accessibility/browser_accessibility_manager_win.h +++ b/content/browser/accessibility/browser_accessibility_manager_win.h
@@ -34,7 +34,7 @@ IAccessible* GetParentIAccessible(); // Calls NotifyWinEvent if the parent window's IAccessible pointer is known. - void MaybeCallNotifyWinEvent(DWORD event, LONG child_id); + void MaybeCallNotifyWinEvent(DWORD event, BrowserAccessibility* node); // AXTree methods virtual void OnNodeWillBeDeleted(ui::AXNode* node) override; @@ -59,7 +59,9 @@ protected: // BrowserAccessibilityManager methods - virtual void OnRootChanged(ui::AXNode* new_root) override; + void OnAtomicUpdateFinished( + bool root_changed, + const std::vector<ui::AXTreeDelegate::Change>& changes) override; private: // Give BrowserAccessibilityManager::Create access to our constructor.
diff --git a/content/browser/accessibility/browser_accessibility_win.cc b/content/browser/accessibility/browser_accessibility_win.cc index 752d1539..eab9196 100644 --- a/content/browser/accessibility/browser_accessibility_win.cc +++ b/content/browser/accessibility/browser_accessibility_win.cc
@@ -175,6 +175,17 @@ } // +// BrowserAccessibilityWin::WinAttributes +// + +BrowserAccessibilityWin::WinAttributes::WinAttributes() + : ia_role(0), + ia_state(0), + ia2_role(0), + ia2_state(0) { +} + +// // BrowserAccessibilityWin // @@ -192,12 +203,7 @@ } BrowserAccessibilityWin::BrowserAccessibilityWin() - : ia_role_(0), - ia_state_(0), - ia2_role_(0), - ia2_state_(0), - first_time_(true), - old_ia_state_(0), + : win_attributes_(new WinAttributes()), previous_scroll_x_(0), previous_scroll_y_(0) { // Start unique IDs at -1 and decrement each time, because get_accChild @@ -382,7 +388,7 @@ return E_INVALIDARG; return target->GetStringAttributeAsBstr( - ui::AX_ATTR_SHORTCUT, def_action); + ui::AX_ATTR_ACTION, def_action); } STDMETHODIMP BrowserAccessibilityWin::get_accDescription(VARIANT var_id, @@ -397,8 +403,14 @@ if (!target) return E_INVALIDARG; - return target->GetStringAttributeAsBstr( - ui::AX_ATTR_DESCRIPTION, desc); + base::string16 description_str = target->description(); + if (description_str.empty()) + return S_FALSE; + + *desc = SysAllocString(description_str.c_str()); + + DCHECK(*desc); + return S_OK; } STDMETHODIMP BrowserAccessibilityWin::get_accFocus(VARIANT* focus_child) { @@ -434,8 +446,14 @@ if (!target) return E_INVALIDARG; - return target->GetStringAttributeAsBstr( - ui::AX_ATTR_HELP, help); + base::string16 help_str = target->help(); + if (help_str.empty()) + return S_FALSE; + + *help = SysAllocString(help_str.c_str()); + + DCHECK(*help); + return S_OK; } STDMETHODIMP BrowserAccessibilityWin::get_accKeyboardShortcut(VARIANT var_id, @@ -465,24 +483,24 @@ if (!target) return E_INVALIDARG; - std::string name_str = target->name(); + base::string16 name_str = target->name(); // If the name is empty, see if it's labeled by another element. if (name_str.empty()) { int title_elem_id; if (target->GetIntAttribute(ui::AX_ATTR_TITLE_UI_ELEMENT, &title_elem_id)) { - BrowserAccessibility* title_elem = - manager()->GetFromID(title_elem_id); + BrowserAccessibilityWin* title_elem = + manager()->GetFromID(title_elem_id)->ToBrowserAccessibilityWin(); if (title_elem) - name_str = title_elem->GetTextRecursive(); + name_str = title_elem->GetNameRecursive(); } } if (name_str.empty()) return S_FALSE; - *name = SysAllocString(base::UTF8ToUTF16(name_str).c_str()); + *name = SysAllocString(name_str.c_str()); DCHECK(*name); return S_OK; @@ -530,12 +548,12 @@ if (!target) return E_INVALIDARG; - if (!target->role_name_.empty()) { + if (!target->role_name().empty()) { role->vt = VT_BSTR; - role->bstrVal = SysAllocString(target->role_name_.c_str()); + role->bstrVal = SysAllocString(target->role_name().c_str()); } else { role->vt = VT_I4; - role->lVal = target->ia_role_; + role->lVal = target->ia_role(); } return S_OK; } @@ -553,7 +571,7 @@ return E_INVALIDARG; state->vt = VT_I4; - state->lVal = target->ia_state_; + state->lVal = target->ia_state(); if (manager()->GetFocus(NULL) == this) state->lVal |= STATE_SYSTEM_FOCUSED; @@ -598,7 +616,7 @@ return S_OK; } - *value = SysAllocString(base::UTF8ToUTF16(target->value()).c_str()); + *value = SysAllocString(target->value().c_str()); DCHECK(*value); return S_OK; } @@ -681,7 +699,7 @@ if (!role) return E_INVALIDARG; - *role = ia2_role_; + *role = ia2_role(); return S_OK; } @@ -716,7 +734,7 @@ if (!states) return E_INVALIDARG; - *states = ia2_state_; + *states = ia2_state(); return S_OK; } @@ -980,8 +998,13 @@ if (!desc) return E_INVALIDARG; - return GetStringAttributeAsBstr( - ui::AX_ATTR_DESCRIPTION, desc); + if (description().empty()) + return S_FALSE; + + *desc = SysAllocString(description().c_str()); + + DCHECK(*desc); + return S_OK; } STDMETHODIMP BrowserAccessibilityWin::get_imagePosition( @@ -1157,8 +1180,10 @@ return S_OK; } - return cell->GetStringAttributeAsBstr( - ui::AX_ATTR_DESCRIPTION, description); + if (cell->description().size() > 0) { + *description = SysAllocString(cell->description().c_str()); + return S_OK; + } } } @@ -1344,8 +1369,10 @@ return S_OK; } - return cell->GetStringAttributeAsBstr( - ui::AX_ATTR_DESCRIPTION, description); + if (cell->description().size() > 0) { + *description = SysAllocString(cell->description().c_str()); + return S_OK; + } } } @@ -2147,11 +2174,15 @@ if (!new_text) return E_INVALIDARG; - base::string16 text = TextForIAccessibleText(); + int start, old_len, new_len; + ComputeHypertextRemovedAndInserted(&start, &old_len, &new_len); + if (new_len == 0) + return E_FAIL; - new_text->text = SysAllocString(text.c_str()); - new_text->start = 0; - new_text->end = static_cast<long>(text.size()); + base::string16 substr = hypertext_.substr(start, new_len); + new_text->text = SysAllocString(substr.c_str()); + new_text->start = static_cast<long>(start); + new_text->end = static_cast<long>(start + new_len); return S_OK; } @@ -2162,9 +2193,15 @@ if (!old_text) return E_INVALIDARG; - old_text->text = SysAllocString(old_text_.c_str()); - old_text->start = 0; - old_text->end = static_cast<long>(old_text_.size()); + int start, old_len, new_len; + ComputeHypertextRemovedAndInserted(&start, &old_len, &new_len); + if (old_len == 0) + return E_FAIL; + + base::string16 substr = old_hypertext_.substr(start, old_len); + old_text->text = SysAllocString(substr.c_str()); + old_text->start = static_cast<long>(start); + old_text->end = static_cast<long>(start + old_len); return S_OK; } @@ -2298,8 +2335,10 @@ *hyperlink_index = -1; - if (char_index < 0 || char_index >= static_cast<long>(hypertext_.size())) + if (char_index < 0 || + char_index >= static_cast<long>(hypertext_.size())) { return E_INVALIDARG; + } std::map<int32, int32>::iterator it = hyperlink_offset_to_index_.find(char_index); @@ -2448,14 +2487,14 @@ *node_name = NULL; *name_space_id = 0; - *node_value = SysAllocString(base::UTF8ToUTF16(value()).c_str()); + *node_value = SysAllocString(value().c_str()); *num_children = PlatformChildCount(); *unique_id = unique_id_win_; - if (ia_role_ == ROLE_SYSTEM_DOCUMENT) { + if (ia_role() == ROLE_SYSTEM_DOCUMENT) { *node_type = NODETYPE_DOCUMENT; - } else if (ia_role_ == ROLE_SYSTEM_TEXT && - ((ia2_state_ & IA2_STATE_EDITABLE) == 0)) { + } else if (ia_role() == ROLE_SYSTEM_TEXT && + ((ia2_state() & IA2_STATE_EDITABLE) == 0)) { *node_type = NODETYPE_TEXT; } else { *node_type = NODETYPE_ELEMENT; @@ -2866,7 +2905,7 @@ void** object) { BrowserAccessibilityWin* accessibility = reinterpret_cast<BrowserAccessibilityWin*>(this_ptr); - int32 ia_role = accessibility->ia_role_; + int32 ia_role = accessibility->ia_role(); if (iid == IID_IAccessibleImage) { if (ia_role != ROLE_SYSTEM_GRAPHIC) { *object = NULL; @@ -2904,12 +2943,28 @@ // Private methods. // -// Called every time this node's data changes. +// Called every time this node's data changes, while the tree update is +// still in progress. void BrowserAccessibilityWin::OnDataChanged() { BrowserAccessibility::OnDataChanged(); +} + +// Called every time this node's data changes, after an atomic tree update. +void BrowserAccessibilityWin::OnUpdateFinished() { + BrowserAccessibility::OnUpdateFinished(); + + if (PlatformIsChildOfLeaf()) + return; + + bool is_new_object = ia_role() == 0 && role_name().empty(); + + old_win_attributes_.swap(win_attributes_); + win_attributes_.reset(new WinAttributes()); InitRoleAndState(); + win_attributes_->ia2_attributes.clear(); + // Expose autocomplete attribute for combobox and textbox. StringAttributeToIA2(ui::AX_ATTR_AUTO_COMPLETE, "autocomplete"); @@ -2926,18 +2981,18 @@ if (GetRole() == ui::AX_ROLE_LIST_BOX_OPTION && GetParent() && GetParent()->GetRole() == ui::AX_ROLE_LIST_BOX) { - ia2_attributes_.push_back( + win_attributes_->ia2_attributes.push_back( L"setsize:" + base::IntToString16(GetParent()->PlatformChildCount())); - ia2_attributes_.push_back( + win_attributes_->ia2_attributes.push_back( L"setsize:" + base::IntToString16(GetIndexInParent() + 1)); } - if (ia_role_ == ROLE_SYSTEM_CHECKBUTTON || - ia_role_ == ROLE_SYSTEM_RADIOBUTTON || - ia2_role_ == IA2_ROLE_CHECK_MENU_ITEM || - ia2_role_ == IA2_ROLE_RADIO_MENU_ITEM || - ia2_role_ == IA2_ROLE_TOGGLE_BUTTON) { - ia2_attributes_.push_back(L"checkable:true"); + if (ia_role() == ROLE_SYSTEM_CHECKBUTTON || + ia_role() == ROLE_SYSTEM_RADIOBUTTON || + ia2_role() == IA2_ROLE_CHECK_MENU_ITEM || + ia2_role() == IA2_ROLE_RADIO_MENU_ITEM || + ia2_role() == IA2_ROLE_TOGGLE_BUTTON) { + win_attributes_->ia2_attributes.push_back(L"checkable:true"); } // Expose live region attributes. @@ -2956,13 +3011,6 @@ BoolAttributeToIA2(ui::AX_ATTR_CONTAINER_LIVE_BUSY, "container-busy"); - // Expose slider value. - if (ia_role_ == ROLE_SYSTEM_PROGRESSBAR || - ia_role_ == ROLE_SYSTEM_SCROLLBAR || - ia_role_ == ROLE_SYSTEM_SLIDER) { - ia2_attributes_.push_back(L"valuetext:" + GetValueText()); - } - // Expose table cell index. if (IsCellOrTableHeaderRole()) { BrowserAccessibility* table = GetParent(); @@ -2973,7 +3021,7 @@ ui::AX_ATTR_UNIQUE_CELL_IDS); for (size_t i = 0; i < unique_cell_ids.size(); ++i) { if (unique_cell_ids[i] == GetId()) { - ia2_attributes_.push_back( + win_attributes_->ia2_attributes.push_back( base::string16(L"table-cell-index:") + base::IntToString16(i)); } } @@ -2989,26 +3037,27 @@ case ui::AX_INVALID_STATE_NONE: break; case ui::AX_INVALID_STATE_FALSE: - ia2_attributes_.push_back(L"invalid:false"); + win_attributes_->ia2_attributes.push_back(L"invalid:false"); break; case ui::AX_INVALID_STATE_TRUE: - ia2_attributes_.push_back(L"invalid:true"); + win_attributes_->ia2_attributes.push_back(L"invalid:true"); break; case ui::AX_INVALID_STATE_SPELLING: - ia2_attributes_.push_back(L"invalid:spelling"); + win_attributes_->ia2_attributes.push_back(L"invalid:spelling"); break; case ui::AX_INVALID_STATE_GRAMMAR: - ia2_attributes_.push_back(L"invalid:grammar"); + win_attributes_->ia2_attributes.push_back(L"invalid:grammar"); break; case ui::AX_INVALID_STATE_OTHER: { base::string16 aria_invalid_value; if (GetString16Attribute(ui::AX_ATTR_ARIA_INVALID_VALUE, &aria_invalid_value)) { - ia2_attributes_.push_back(L"invalid:" + aria_invalid_value); + win_attributes_->ia2_attributes.push_back( + L"invalid:" + aria_invalid_value); } else { // Set the attribute to L"true", since we cannot be more specific. - ia2_attributes_.push_back(L"invalid:true"); + win_attributes_->ia2_attributes.push_back(L"invalid:true"); } } break; @@ -3038,16 +3087,16 @@ // always returns the primary name in "name" and the secondary name, // if any, in "description". - int title_elem_id = GetIntAttribute( - ui::AX_ATTR_TITLE_UI_ELEMENT); - std::string help = GetStringAttribute(ui::AX_ATTR_HELP); - std::string description = GetStringAttribute( - ui::AX_ATTR_DESCRIPTION); + int title_elem_id = GetIntAttribute(ui::AX_ATTR_TITLE_UI_ELEMENT); + base::string16 name = GetString16Attribute(ui::AX_ATTR_NAME); + base::string16 description = GetString16Attribute(ui::AX_ATTR_DESCRIPTION); + base::string16 help = GetString16Attribute(ui::AX_ATTR_HELP); + base::string16 value = GetString16Attribute(ui::AX_ATTR_VALUE); // WebKit annoyingly puts the title in the description if there's no other // description, which just confuses the rest of the logic. Put it back. // Now "help" is always the value of the "title" attribute, if present. - std::string title_attr; + base::string16 title_attr; if (GetHtmlAttribute("title", &title_attr) && description == title_attr && help.empty()) { @@ -3059,55 +3108,57 @@ // it's nonempty, and the help should become the description if // there's no description - or the name if there's no name or description. if (!description.empty()) { - set_name(description); + name = description; description.clear(); } if (!help.empty() && description.empty()) { description = help; help.clear(); } - if (!description.empty() && name().empty() && !title_elem_id) { - set_name(description); + if (!description.empty() && name.empty() && !title_elem_id) { + name = description; description.clear(); } // If it's a text field, also consider the placeholder. - std::string placeholder; + base::string16 placeholder; if (GetRole() == ui::AX_ROLE_TEXT_FIELD && HasState(ui::AX_STATE_FOCUSABLE) && GetHtmlAttribute("placeholder", &placeholder)) { - if (name().empty() && !title_elem_id) { - set_name(placeholder); + if (name.empty() && !title_elem_id) { + name = placeholder; } else if (description.empty()) { description = placeholder; } } - SetStringAttribute(ui::AX_ATTR_DESCRIPTION, description); - SetStringAttribute(ui::AX_ATTR_HELP, help); - // On Windows, the value of a document should be its url. if (GetRole() == ui::AX_ROLE_ROOT_WEB_AREA || GetRole() == ui::AX_ROLE_WEB_AREA) { - set_value(GetStringAttribute(ui::AX_ATTR_DOC_URL)); + value = GetString16Attribute(ui::AX_ATTR_DOC_URL); } // For certain roles (listbox option, static text, and list marker) // WebKit stores the main accessible text in the "value" - swap it so // that it's the "name". - if (name().empty() && + if (name.empty() && (GetRole() == ui::AX_ROLE_LIST_BOX_OPTION || GetRole() == ui::AX_ROLE_STATIC_TEXT || GetRole() == ui::AX_ROLE_LIST_MARKER)) { - std::string tmp = value(); - set_value(name()); - set_name(tmp); + base::string16 tmp = value; + value = name; + name = tmp; } // If this doesn't have a value and is linked then set its value to the url // attribute. This allows screen readers to read an empty link's destination. - if (value().empty() && (ia_state_ & STATE_SYSTEM_LINKED)) - set_value(GetStringAttribute(ui::AX_ATTR_URL)); + if (value.empty() && (ia_state() & STATE_SYSTEM_LINKED)) + value = GetString16Attribute(ui::AX_ATTR_URL); + + win_attributes_->name = name; + win_attributes_->description = description; + win_attributes_->help = help; + win_attributes_->value = value; // Clear any old relationships between this node and other nodes. for (size_t i = 0; i < relations_.size(); ++i) @@ -3127,95 +3178,138 @@ relations_.push_back(relation); } + // Expose slider value. + if (ia_role() == ROLE_SYSTEM_PROGRESSBAR || + ia_role() == ROLE_SYSTEM_SCROLLBAR || + ia_role() == ROLE_SYSTEM_SLIDER) { + win_attributes_->ia2_attributes.push_back(L"valuetext:" + GetValueText()); + } + // If this is a web area for a presentational iframe, give it a role of // something other than DOCUMENT so that the fact that it's a separate doc // is not exposed to AT. if (IsWebAreaForPresentationalIframe()) { - ia_role_ = ROLE_SYSTEM_GROUPING; - ia2_role_ = ROLE_SYSTEM_GROUPING; + win_attributes_->ia_role = ROLE_SYSTEM_GROUPING; + win_attributes_->ia2_role = ROLE_SYSTEM_GROUPING; } + + BrowserAccessibilityManagerWin* manager = + this->manager()->ToBrowserAccessibilityManagerWin(); + + // Fire an event when an alert first appears. + if (ia_role() == ROLE_SYSTEM_ALERT && + old_win_attributes_->ia_role != ROLE_SYSTEM_ALERT) { + manager->NotifyAccessibilityEvent(ui::AX_EVENT_ALERT, this); + } + + // Fire an event if the name, description, help, or value changes. + if (!is_new_object) { + if (name != old_win_attributes_->name) + manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_NAMECHANGE, this); + if (description != old_win_attributes_->description) + manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_DESCRIPTIONCHANGE, this); + if (help != old_win_attributes_->help) + manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_HELPCHANGE, this); + if (value != old_win_attributes_->value) + manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_VALUECHANGE, this); + if (ia_state() != old_win_attributes_->ia_state) + manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_STATECHANGE, this); + + // Normally focus events are handled elsewhere, however + // focus for managed descendants is platform-specific. + // Fire a focus event if the focused descendant in a multi-select + // list box changes. + if (GetRole() == ui::AX_ROLE_LIST_BOX_OPTION && + (ia_state() & STATE_SYSTEM_FOCUSABLE) && + (ia_state() & STATE_SYSTEM_SELECTABLE) && + (ia_state() & STATE_SYSTEM_FOCUSED) && + !(old_win_attributes_->ia_state & STATE_SYSTEM_FOCUSED)) { + manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_FOCUS, this); + } + + // Handle selection being added or removed. + bool is_selected_now = (ia_state() & STATE_SYSTEM_SELECTED) != 0; + bool was_selected_before = + (old_win_attributes_->ia_state & STATE_SYSTEM_SELECTED) != 0; + if (is_selected_now && !was_selected_before) { + manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_SELECTIONADD, this); + } else if (!is_selected_now && was_selected_before) { + manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_SELECTIONREMOVE, this); + } + + // Fire an event if this container object has scrolled. + int sx = 0; + int sy = 0; + if (GetIntAttribute(ui::AX_ATTR_SCROLL_X, &sx) && + GetIntAttribute(ui::AX_ATTR_SCROLL_Y, &sy)) { + if (sx != previous_scroll_x_ || sy != previous_scroll_y_) + manager->MaybeCallNotifyWinEvent(EVENT_SYSTEM_SCROLLINGEND, this); + previous_scroll_x_ = sx; + previous_scroll_y_ = sy; + } + + // Changing a static text node can affect the IAccessibleText hypertext + // of the parent node, so force it to be recomputed here. + if (GetParent() && + GetRole() == ui::AX_ROLE_STATIC_TEXT && + name != old_win_attributes_->name) { + GetParent()->ToBrowserAccessibilityWin()->UpdateIAccessibleText(); + } + } + + old_win_attributes_.reset(nullptr); } -void BrowserAccessibilityWin::OnUpdateFinished() { +void BrowserAccessibilityWin::UpdateIAccessibleText() { + old_hypertext_ = hypertext_; + hypertext_.clear(); + // Construct the hypertext for this node. hyperlink_offset_to_index_.clear(); hyperlinks_.clear(); - hypertext_.clear(); for (unsigned int i = 0; i < PlatformChildCount(); ++i) { - BrowserAccessibility* child = PlatformGetChild(i); + BrowserAccessibilityWin* child = + PlatformGetChild(i)->ToBrowserAccessibilityWin(); if (child->GetRole() == ui::AX_ROLE_STATIC_TEXT) { - hypertext_ += base::UTF8ToUTF16(child->name()); + hypertext_ += child->name(); } else { - hyperlink_offset_to_index_[hypertext_.size()] = hyperlinks_.size(); + hyperlink_offset_to_index_[hypertext_.size()] = + hyperlinks_.size(); hypertext_ += kEmbeddedCharacter; hyperlinks_.push_back(i); } } DCHECK_EQ(hyperlink_offset_to_index_.size(), hyperlinks_.size()); - // Fire an event when an alert first appears. - if (GetRole() == ui::AX_ROLE_ALERT && first_time_) - manager()->NotifyAccessibilityEvent(ui::AX_EVENT_ALERT, this); + if (hypertext_ != old_hypertext_) { + BrowserAccessibilityManagerWin* manager = + this->manager()->ToBrowserAccessibilityManagerWin(); - // Fire events if text has changed. - base::string16 text = TextForIAccessibleText(); - if (previous_text_ != text) { - if (!previous_text_.empty() && !text.empty()) { - manager()->NotifyAccessibilityEvent( - ui::AX_EVENT_SHOW, this); + int start, old_len, new_len; + ComputeHypertextRemovedAndInserted(&start, &old_len, &new_len); + if (old_len) { + // In-process screen readers may call IAccessibleText::get_oldText + // to retrieve the text that was removed. + manager->MaybeCallNotifyWinEvent(IA2_EVENT_TEXT_REMOVED, this); } - - // TODO(dmazzoni): Look into HIDE events, too. - - old_text_ = previous_text_; - previous_text_ = text; + if (new_len) { + // In-process screen readers may call IAccessibleText::get_newText + // to retrieve the text that was inserted. + manager->MaybeCallNotifyWinEvent(IA2_EVENT_TEXT_INSERTED, this); + } } - BrowserAccessibilityManagerWin* manager = - this->manager()->ToBrowserAccessibilityManagerWin(); + old_hypertext_.clear(); +} - // Fire events if the state has changed. - if (!first_time_ && ia_state_ != old_ia_state_) { - // Normally focus events are handled elsewhere, however - // focus for managed descendants is platform-specific. - // Fire a focus event if the focused descendant in a multi-select - // list box changes. - if (GetRole() == ui::AX_ROLE_LIST_BOX_OPTION && - (ia_state_ & STATE_SYSTEM_FOCUSABLE) && - (ia_state_ & STATE_SYSTEM_SELECTABLE) && - (ia_state_ & STATE_SYSTEM_FOCUSED) && - !(old_ia_state_ & STATE_SYSTEM_FOCUSED)) { - manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_FOCUS, unique_id_win()); - } +void BrowserAccessibilityWin::OnSubtreeWillBeDeleted() { + manager()->ToBrowserAccessibilityManagerWin()->MaybeCallNotifyWinEvent( + EVENT_OBJECT_HIDE, this); +} - if ((ia_state_ & STATE_SYSTEM_SELECTED) && - !(old_ia_state_ & STATE_SYSTEM_SELECTED)) { - manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_SELECTIONADD, - unique_id_win()); - } else if (!(ia_state_ & STATE_SYSTEM_SELECTED) && - (old_ia_state_ & STATE_SYSTEM_SELECTED)) { - manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_SELECTIONREMOVE, - unique_id_win()); - } - - old_ia_state_ = ia_state_; - } - - // Fire an event if this container object has scrolled. - int sx = 0; - int sy = 0; - if (GetIntAttribute(ui::AX_ATTR_SCROLL_X, &sx) && - GetIntAttribute(ui::AX_ATTR_SCROLL_Y, &sy)) { - if (!first_time_ && - (sx != previous_scroll_x_ || sy != previous_scroll_y_)) { - manager->MaybeCallNotifyWinEvent(EVENT_SYSTEM_SCROLLINGEND, - unique_id_win()); - } - previous_scroll_x_ = sx; - previous_scroll_y_ = sy; - } - - first_time_ = false; +void BrowserAccessibilityWin::OnSubtreeCreationFinished() { + manager()->ToBrowserAccessibilityManagerWin()->MaybeCallNotifyWinEvent( + EVENT_OBJECT_SHOW, this); } void BrowserAccessibilityWin::NativeAddReference() { @@ -3232,7 +3326,7 @@ void BrowserAccessibilityWin::OnLocationChanged() { manager()->ToBrowserAccessibilityManagerWin()->MaybeCallNotifyWinEvent( - EVENT_OBJECT_LOCATIONCHANGE, unique_id_win()); + EVENT_OBJECT_LOCATIONCHANGE, this); } BrowserAccessibilityWin* BrowserAccessibilityWin::NewReference() { @@ -3277,8 +3371,10 @@ ui::AXStringAttribute attribute, const char* ia2_attr) { base::string16 value; - if (GetString16Attribute(attribute, &value)) - ia2_attributes_.push_back(base::ASCIIToUTF16(ia2_attr) + L":" + value); + if (GetString16Attribute(attribute, &value)) { + win_attributes_->ia2_attributes.push_back( + base::ASCIIToUTF16(ia2_attr) + L":" + value); + } } void BrowserAccessibilityWin::BoolAttributeToIA2( @@ -3286,8 +3382,9 @@ const char* ia2_attr) { bool value; if (GetBoolAttribute(attribute, &value)) { - ia2_attributes_.push_back((base::ASCIIToUTF16(ia2_attr) + L":") + - (value ? L"true" : L"false")); + win_attributes_->ia2_attributes.push_back( + (base::ASCIIToUTF16(ia2_attr) + L":") + + (value ? L"true" : L"false")); } } @@ -3296,14 +3393,28 @@ const char* ia2_attr) { int value; if (GetIntAttribute(attribute, &value)) { - ia2_attributes_.push_back(base::ASCIIToUTF16(ia2_attr) + L":" + - base::IntToString16(value)); + win_attributes_->ia2_attributes.push_back( + base::ASCIIToUTF16(ia2_attr) + L":" + + base::IntToString16(value)); } } +base::string16 BrowserAccessibilityWin::GetNameRecursive() const { + if (!name().empty()) { + return name(); + } + + base::string16 result; + for (uint32 i = 0; i < PlatformChildCount(); ++i) { + result += PlatformGetChild(i)->ToBrowserAccessibilityWin()-> + GetNameRecursive(); + } + return result; +} + base::string16 BrowserAccessibilityWin::GetValueText() { float fval; - base::string16 value = base::UTF8ToUTF16(this->value()); + base::string16 value = this->value(); if (value.empty() && GetFloatAttribute(ui::AX_ATTR_VALUE_FOR_RANGE, &fval)) { @@ -3314,9 +3425,37 @@ base::string16 BrowserAccessibilityWin::TextForIAccessibleText() { if (IsEditableText()) - return base::UTF8ToUTF16(value()); - return (GetRole() == ui::AX_ROLE_STATIC_TEXT) ? - base::UTF8ToUTF16(name()) : hypertext_; + return value(); + return (GetRole() == ui::AX_ROLE_STATIC_TEXT) ? name() : hypertext_; +} + +void BrowserAccessibilityWin::ComputeHypertextRemovedAndInserted( + int* start, int* old_len, int* new_len) { + *start = 0; + *old_len = 0; + *new_len = 0; + + const base::string16& old_text = old_hypertext_; + const base::string16& new_text = hypertext_; + + size_t common_prefix = 0; + while (common_prefix < old_text.size() && + common_prefix < new_text.size() && + old_text[common_prefix] == new_text[common_prefix]) { + ++common_prefix; + } + + size_t common_suffix = 0; + while (common_prefix + common_suffix < old_text.size() && + common_prefix + common_suffix < new_text.size() && + old_text[old_text.size() - common_suffix - 1] == + new_text[new_text.size() - common_suffix - 1]) { + ++common_suffix; + } + + *start = common_prefix; + *old_len = old_text.size() - common_prefix - common_suffix; + *new_len = new_text.size() - common_prefix - common_suffix; } void BrowserAccessibilityWin::HandleSpecialTextOffset( @@ -3367,499 +3506,499 @@ } void BrowserAccessibilityWin::InitRoleAndState() { - ia_state_ = 0; - ia2_state_ = IA2_STATE_OPAQUE; - ia2_attributes_.clear(); + int32 ia_role = 0; + int32 ia_state = 0; + base::string16 role_name; + int32 ia2_role = 0; + int32 ia2_state = IA2_STATE_OPAQUE; if (HasState(ui::AX_STATE_BUSY)) - ia_state_ |= STATE_SYSTEM_BUSY; + ia_state |= STATE_SYSTEM_BUSY; if (HasState(ui::AX_STATE_CHECKED)) - ia_state_ |= STATE_SYSTEM_CHECKED; + ia_state |= STATE_SYSTEM_CHECKED; if (HasState(ui::AX_STATE_COLLAPSED)) - ia_state_ |= STATE_SYSTEM_COLLAPSED; + ia_state |= STATE_SYSTEM_COLLAPSED; if (HasState(ui::AX_STATE_EXPANDED)) - ia_state_ |= STATE_SYSTEM_EXPANDED; + ia_state |= STATE_SYSTEM_EXPANDED; if (HasState(ui::AX_STATE_FOCUSABLE)) - ia_state_ |= STATE_SYSTEM_FOCUSABLE; + ia_state |= STATE_SYSTEM_FOCUSABLE; if (HasState(ui::AX_STATE_HASPOPUP)) - ia_state_ |= STATE_SYSTEM_HASPOPUP; + ia_state |= STATE_SYSTEM_HASPOPUP; if (HasState(ui::AX_STATE_HOVERED)) - ia_state_ |= STATE_SYSTEM_HOTTRACKED; + ia_state |= STATE_SYSTEM_HOTTRACKED; if (HasState(ui::AX_STATE_INDETERMINATE)) - ia_state_ |= STATE_SYSTEM_INDETERMINATE; + ia_state |= STATE_SYSTEM_INDETERMINATE; if (HasIntAttribute(ui::AX_ATTR_INVALID_STATE) && GetIntAttribute(ui::AX_ATTR_INVALID_STATE) != ui::AX_INVALID_STATE_FALSE) - ia2_state_ |= IA2_STATE_INVALID_ENTRY; + ia2_state |= IA2_STATE_INVALID_ENTRY; if (HasState(ui::AX_STATE_INVISIBLE)) - ia_state_ |= STATE_SYSTEM_INVISIBLE; + ia_state |= STATE_SYSTEM_INVISIBLE; if (HasState(ui::AX_STATE_LINKED)) - ia_state_ |= STATE_SYSTEM_LINKED; + ia_state |= STATE_SYSTEM_LINKED; if (HasState(ui::AX_STATE_MULTISELECTABLE)) { - ia_state_ |= STATE_SYSTEM_EXTSELECTABLE; - ia_state_ |= STATE_SYSTEM_MULTISELECTABLE; + ia_state |= STATE_SYSTEM_EXTSELECTABLE; + ia_state |= STATE_SYSTEM_MULTISELECTABLE; } // TODO(ctguil): Support STATE_SYSTEM_EXTSELECTABLE/accSelect. if (HasState(ui::AX_STATE_OFFSCREEN)) - ia_state_ |= STATE_SYSTEM_OFFSCREEN; + ia_state |= STATE_SYSTEM_OFFSCREEN; if (HasState(ui::AX_STATE_PRESSED)) - ia_state_ |= STATE_SYSTEM_PRESSED; + ia_state |= STATE_SYSTEM_PRESSED; if (HasState(ui::AX_STATE_PROTECTED)) - ia_state_ |= STATE_SYSTEM_PROTECTED; + ia_state |= STATE_SYSTEM_PROTECTED; if (HasState(ui::AX_STATE_REQUIRED)) - ia2_state_ |= IA2_STATE_REQUIRED; + ia2_state |= IA2_STATE_REQUIRED; if (HasState(ui::AX_STATE_SELECTABLE)) - ia_state_ |= STATE_SYSTEM_SELECTABLE; + ia_state |= STATE_SYSTEM_SELECTABLE; if (HasState(ui::AX_STATE_SELECTED)) - ia_state_ |= STATE_SYSTEM_SELECTED; + ia_state |= STATE_SYSTEM_SELECTED; if (HasState(ui::AX_STATE_VISITED)) - ia_state_ |= STATE_SYSTEM_TRAVERSED; + ia_state |= STATE_SYSTEM_TRAVERSED; if (!HasState(ui::AX_STATE_ENABLED)) - ia_state_ |= STATE_SYSTEM_UNAVAILABLE; + ia_state |= STATE_SYSTEM_UNAVAILABLE; if (HasState(ui::AX_STATE_VERTICAL)) - ia2_state_ |= IA2_STATE_VERTICAL; + ia2_state |= IA2_STATE_VERTICAL; if (HasState(ui::AX_STATE_HORIZONTAL)) - ia2_state_ |= IA2_STATE_HORIZONTAL; + ia2_state |= IA2_STATE_HORIZONTAL; if (HasState(ui::AX_STATE_VISITED)) - ia_state_ |= STATE_SYSTEM_TRAVERSED; + ia_state |= STATE_SYSTEM_TRAVERSED; // WebKit marks everything as readonly unless it's editable text, so if it's // not readonly, mark it as editable now. The final computation of the // READONLY state for MSAA is below, after the switch. if (!HasState(ui::AX_STATE_READ_ONLY)) - ia2_state_ |= IA2_STATE_EDITABLE; + ia2_state |= IA2_STATE_EDITABLE; if (GetBoolAttribute(ui::AX_ATTR_BUTTON_MIXED)) - ia_state_ |= STATE_SYSTEM_MIXED; + ia_state |= STATE_SYSTEM_MIXED; if (GetBoolAttribute(ui::AX_ATTR_CAN_SET_VALUE)) - ia2_state_ |= IA2_STATE_EDITABLE; + ia2_state |= IA2_STATE_EDITABLE; if (!GetStringAttribute(ui::AX_ATTR_AUTO_COMPLETE).empty()) - ia2_state_ |= IA2_STATE_SUPPORTS_AUTOCOMPLETION; + ia2_state |= IA2_STATE_SUPPORTS_AUTOCOMPLETION; base::string16 html_tag = GetString16Attribute( ui::AX_ATTR_HTML_TAG); - ia_role_ = 0; - ia2_role_ = 0; switch (GetRole()) { case ui::AX_ROLE_ALERT: - ia_role_ = ROLE_SYSTEM_ALERT; + ia_role = ROLE_SYSTEM_ALERT; break; case ui::AX_ROLE_ALERT_DIALOG: - ia_role_ = ROLE_SYSTEM_DIALOG; + ia_role = ROLE_SYSTEM_DIALOG; break; case ui::AX_ROLE_APPLICATION: - ia_role_ = ROLE_SYSTEM_APPLICATION; + ia_role = ROLE_SYSTEM_APPLICATION; break; case ui::AX_ROLE_ARTICLE: - ia_role_ = ROLE_SYSTEM_DOCUMENT; - ia_state_ |= STATE_SYSTEM_READONLY; + ia_role = ROLE_SYSTEM_DOCUMENT; + ia_state |= STATE_SYSTEM_READONLY; break; case ui::AX_ROLE_BANNER: - ia_role_ = ROLE_SYSTEM_GROUPING; - ia2_role_ = IA2_ROLE_HEADER; + ia_role = ROLE_SYSTEM_GROUPING; + ia2_role = IA2_ROLE_HEADER; break; case ui::AX_ROLE_BLOCKQUOTE: - role_name_ = html_tag; - ia2_role_ = IA2_ROLE_SECTION; + role_name = html_tag; + ia2_role = IA2_ROLE_SECTION; break; case ui::AX_ROLE_BUSY_INDICATOR: - ia_role_ = ROLE_SYSTEM_ANIMATION; - ia_state_ |= STATE_SYSTEM_READONLY; + ia_role = ROLE_SYSTEM_ANIMATION; + ia_state |= STATE_SYSTEM_READONLY; break; case ui::AX_ROLE_BUTTON: - ia_role_ = ROLE_SYSTEM_PUSHBUTTON; + ia_role = ROLE_SYSTEM_PUSHBUTTON; break; case ui::AX_ROLE_CANVAS: if (GetBoolAttribute(ui::AX_ATTR_CANVAS_HAS_FALLBACK)) { - role_name_ = L"canvas"; - ia2_role_ = IA2_ROLE_CANVAS; + role_name = L"canvas"; + ia2_role = IA2_ROLE_CANVAS; } else { - ia_role_ = ROLE_SYSTEM_GRAPHIC; + ia_role = ROLE_SYSTEM_GRAPHIC; } break; case ui::AX_ROLE_CAPTION: - ia_role_ = ROLE_SYSTEM_TEXT; - ia2_role_ = IA2_ROLE_CAPTION; + ia_role = ROLE_SYSTEM_TEXT; + ia2_role = IA2_ROLE_CAPTION; break; case ui::AX_ROLE_CELL: - ia_role_ = ROLE_SYSTEM_CELL; + ia_role = ROLE_SYSTEM_CELL; break; case ui::AX_ROLE_CHECK_BOX: - ia_role_ = ROLE_SYSTEM_CHECKBUTTON; - ia2_state_ |= IA2_STATE_CHECKABLE; + ia_role = ROLE_SYSTEM_CHECKBUTTON; + ia2_state |= IA2_STATE_CHECKABLE; break; case ui::AX_ROLE_COLOR_WELL: - ia_role_ = ROLE_SYSTEM_TEXT; - ia2_role_ = IA2_ROLE_COLOR_CHOOSER; + ia_role = ROLE_SYSTEM_TEXT; + ia2_role = IA2_ROLE_COLOR_CHOOSER; break; case ui::AX_ROLE_COLUMN: - ia_role_ = ROLE_SYSTEM_COLUMN; + ia_role = ROLE_SYSTEM_COLUMN; break; case ui::AX_ROLE_COLUMN_HEADER: - ia_role_ = ROLE_SYSTEM_COLUMNHEADER; + ia_role = ROLE_SYSTEM_COLUMNHEADER; break; case ui::AX_ROLE_COMBO_BOX: - ia_role_ = ROLE_SYSTEM_COMBOBOX; + ia_role = ROLE_SYSTEM_COMBOBOX; break; case ui::AX_ROLE_COMPLEMENTARY: - ia_role_ = ROLE_SYSTEM_GROUPING; - ia2_role_ = IA2_ROLE_NOTE; + ia_role = ROLE_SYSTEM_GROUPING; + ia2_role = IA2_ROLE_NOTE; break; case ui::AX_ROLE_CONTENT_INFO: - ia_role_ = ROLE_SYSTEM_TEXT; - ia2_role_ = IA2_ROLE_PARAGRAPH; + ia_role = ROLE_SYSTEM_TEXT; + ia2_role = IA2_ROLE_PARAGRAPH; break; case ui::AX_ROLE_DATE: case ui::AX_ROLE_DATE_TIME: - ia_role_ = ROLE_SYSTEM_DROPLIST; - ia2_role_ = IA2_ROLE_DATE_EDITOR; + ia_role = ROLE_SYSTEM_DROPLIST; + ia2_role = IA2_ROLE_DATE_EDITOR; break; case ui::AX_ROLE_DIV: - role_name_ = L"div"; - ia_role_ = ROLE_SYSTEM_GROUPING; - ia2_role_ = IA2_ROLE_SECTION; + role_name = L"div"; + ia_role = ROLE_SYSTEM_GROUPING; + ia2_role = IA2_ROLE_SECTION; break; case ui::AX_ROLE_DEFINITION: - role_name_ = html_tag; - ia2_role_ = IA2_ROLE_PARAGRAPH; - ia_state_ |= STATE_SYSTEM_READONLY; + role_name = html_tag; + ia2_role = IA2_ROLE_PARAGRAPH; + ia_state |= STATE_SYSTEM_READONLY; break; case ui::AX_ROLE_DESCRIPTION_LIST_DETAIL: - role_name_ = html_tag; - ia_role_ = ROLE_SYSTEM_TEXT; - ia2_role_ = IA2_ROLE_PARAGRAPH; + role_name = html_tag; + ia_role = ROLE_SYSTEM_TEXT; + ia2_role = IA2_ROLE_PARAGRAPH; break; case ui::AX_ROLE_DESCRIPTION_LIST: - role_name_ = html_tag; - ia_role_ = ROLE_SYSTEM_LIST; - ia_state_ |= STATE_SYSTEM_READONLY; + role_name = html_tag; + ia_role = ROLE_SYSTEM_LIST; + ia_state |= STATE_SYSTEM_READONLY; break; case ui::AX_ROLE_DESCRIPTION_LIST_TERM: - ia_role_ = ROLE_SYSTEM_LISTITEM; - ia_state_ |= STATE_SYSTEM_READONLY; + ia_role = ROLE_SYSTEM_LISTITEM; + ia_state |= STATE_SYSTEM_READONLY; break; case ui::AX_ROLE_DETAILS: - role_name_ = html_tag; - ia_role_ = ROLE_SYSTEM_GROUPING; + role_name = html_tag; + ia_role = ROLE_SYSTEM_GROUPING; break; case ui::AX_ROLE_DIALOG: - ia_role_ = ROLE_SYSTEM_DIALOG; + ia_role = ROLE_SYSTEM_DIALOG; break; case ui::AX_ROLE_DISCLOSURE_TRIANGLE: - ia_role_ = ROLE_SYSTEM_PUSHBUTTON; + ia_role = ROLE_SYSTEM_PUSHBUTTON; break; case ui::AX_ROLE_DOCUMENT: case ui::AX_ROLE_ROOT_WEB_AREA: case ui::AX_ROLE_WEB_AREA: - ia_role_ = ROLE_SYSTEM_DOCUMENT; - ia_state_ |= STATE_SYSTEM_READONLY; - ia_state_ |= STATE_SYSTEM_FOCUSABLE; + ia_role = ROLE_SYSTEM_DOCUMENT; + ia_state |= STATE_SYSTEM_READONLY; + ia_state |= STATE_SYSTEM_FOCUSABLE; break; case ui::AX_ROLE_EMBEDDED_OBJECT: - ia_role_ = ROLE_SYSTEM_CLIENT; - ia2_role_ = IA2_ROLE_EMBEDDED_OBJECT; + ia_role = ROLE_SYSTEM_CLIENT; + ia2_role = IA2_ROLE_EMBEDDED_OBJECT; break; case ui::AX_ROLE_FIGCAPTION: - role_name_ = html_tag; - ia2_role_ = IA2_ROLE_CAPTION; + role_name = html_tag; + ia2_role = IA2_ROLE_CAPTION; break; case ui::AX_ROLE_FIGURE: - ia_role_ = ROLE_SYSTEM_GROUPING; + ia_role = ROLE_SYSTEM_GROUPING; break; case ui::AX_ROLE_FORM: - role_name_ = L"form"; - ia2_role_ = IA2_ROLE_FORM; + role_name = L"form"; + ia2_role = IA2_ROLE_FORM; break; case ui::AX_ROLE_FOOTER: - ia_role_ = ROLE_SYSTEM_GROUPING; - ia2_role_ = IA2_ROLE_FOOTER; + ia_role = ROLE_SYSTEM_GROUPING; + ia2_role = IA2_ROLE_FOOTER; break; case ui::AX_ROLE_GRID: - ia_role_ = ROLE_SYSTEM_TABLE; - ia_state_ |= STATE_SYSTEM_READONLY; + ia_role = ROLE_SYSTEM_TABLE; + ia_state |= STATE_SYSTEM_READONLY; break; case ui::AX_ROLE_GROUP: { base::string16 aria_role = GetString16Attribute( ui::AX_ATTR_ROLE); if (aria_role == L"group" || html_tag == L"fieldset") { - ia_role_ = ROLE_SYSTEM_GROUPING; + ia_role = ROLE_SYSTEM_GROUPING; } else if (html_tag == L"li") { - ia_role_ = ROLE_SYSTEM_LISTITEM; - ia_state_ |= STATE_SYSTEM_READONLY; + ia_role = ROLE_SYSTEM_LISTITEM; + ia_state |= STATE_SYSTEM_READONLY; } else { if (html_tag.empty()) - role_name_ = L"div"; + role_name = L"div"; else - role_name_ = html_tag; - ia2_role_ = IA2_ROLE_SECTION; + role_name = html_tag; + ia2_role = IA2_ROLE_SECTION; } break; } case ui::AX_ROLE_HEADING: - role_name_ = html_tag; - ia2_role_ = IA2_ROLE_HEADING; + role_name = html_tag; + ia2_role = IA2_ROLE_HEADING; break; case ui::AX_ROLE_IFRAME: - ia_role_ = ROLE_SYSTEM_DOCUMENT; - ia2_role_ = IA2_ROLE_INTERNAL_FRAME; - ia_state_ = STATE_SYSTEM_READONLY; + ia_role = ROLE_SYSTEM_DOCUMENT; + ia2_role = IA2_ROLE_INTERNAL_FRAME; + ia_state = STATE_SYSTEM_READONLY; break; case ui::AX_ROLE_IFRAME_PRESENTATIONAL: - ia_role_ = ROLE_SYSTEM_GROUPING; + ia_role = ROLE_SYSTEM_GROUPING; break; case ui::AX_ROLE_IMAGE: - ia_role_ = ROLE_SYSTEM_GRAPHIC; - ia_state_ |= STATE_SYSTEM_READONLY; + ia_role = ROLE_SYSTEM_GRAPHIC; + ia_state |= STATE_SYSTEM_READONLY; break; case ui::AX_ROLE_IMAGE_MAP: - role_name_ = html_tag; - ia2_role_ = IA2_ROLE_IMAGE_MAP; - ia_state_ |= STATE_SYSTEM_READONLY; + role_name = html_tag; + ia2_role = IA2_ROLE_IMAGE_MAP; + ia_state |= STATE_SYSTEM_READONLY; break; case ui::AX_ROLE_IMAGE_MAP_LINK: - ia_role_ = ROLE_SYSTEM_LINK; - ia_state_ |= STATE_SYSTEM_LINKED; - ia_state_ |= STATE_SYSTEM_READONLY; + ia_role = ROLE_SYSTEM_LINK; + ia_state |= STATE_SYSTEM_LINKED; + ia_state |= STATE_SYSTEM_READONLY; break; case ui::AX_ROLE_LABEL_TEXT: case ui::AX_ROLE_LEGEND: - ia_role_ = ROLE_SYSTEM_TEXT; - ia2_role_ = IA2_ROLE_LABEL; + ia_role = ROLE_SYSTEM_TEXT; + ia2_role = IA2_ROLE_LABEL; break; case ui::AX_ROLE_SEARCH: - ia_role_ = ROLE_SYSTEM_GROUPING; - ia2_role_ = IA2_ROLE_SECTION; + ia_role = ROLE_SYSTEM_GROUPING; + ia2_role = IA2_ROLE_SECTION; break; case ui::AX_ROLE_LINK: - ia_role_ = ROLE_SYSTEM_LINK; - ia_state_ |= STATE_SYSTEM_LINKED; + ia_role = ROLE_SYSTEM_LINK; + ia_state |= STATE_SYSTEM_LINKED; break; case ui::AX_ROLE_LIST: - ia_role_ = ROLE_SYSTEM_LIST; - ia_state_ |= STATE_SYSTEM_READONLY; + ia_role = ROLE_SYSTEM_LIST; + ia_state |= STATE_SYSTEM_READONLY; break; case ui::AX_ROLE_LIST_BOX: - ia_role_ = ROLE_SYSTEM_LIST; + ia_role = ROLE_SYSTEM_LIST; break; case ui::AX_ROLE_LIST_BOX_OPTION: - ia_role_ = ROLE_SYSTEM_LISTITEM; - if (ia_state_ & STATE_SYSTEM_SELECTABLE) { - ia_state_ |= STATE_SYSTEM_FOCUSABLE; + ia_role = ROLE_SYSTEM_LISTITEM; + if (ia_state & STATE_SYSTEM_SELECTABLE) { + ia_state |= STATE_SYSTEM_FOCUSABLE; if (HasState(ui::AX_STATE_FOCUSED)) - ia_state_ |= STATE_SYSTEM_FOCUSED; + ia_state |= STATE_SYSTEM_FOCUSED; } break; case ui::AX_ROLE_LIST_ITEM: - ia_role_ = ROLE_SYSTEM_LISTITEM; - ia_state_ |= STATE_SYSTEM_READONLY; + ia_role = ROLE_SYSTEM_LISTITEM; + ia_state |= STATE_SYSTEM_READONLY; break; case ui::AX_ROLE_MAIN: - ia_role_ = ROLE_SYSTEM_GROUPING; - ia2_role_ = IA2_ROLE_PARAGRAPH; + ia_role = ROLE_SYSTEM_GROUPING; + ia2_role = IA2_ROLE_PARAGRAPH; break; case ui::AX_ROLE_MARQUEE: - ia_role_ = ROLE_SYSTEM_ANIMATION; + ia_role = ROLE_SYSTEM_ANIMATION; break; case ui::AX_ROLE_MATH: - ia_role_ = ROLE_SYSTEM_EQUATION; + ia_role = ROLE_SYSTEM_EQUATION; break; case ui::AX_ROLE_MENU: case ui::AX_ROLE_MENU_BUTTON: - ia_role_ = ROLE_SYSTEM_MENUPOPUP; + ia_role = ROLE_SYSTEM_MENUPOPUP; break; case ui::AX_ROLE_MENU_BAR: - ia_role_ = ROLE_SYSTEM_MENUBAR; + ia_role = ROLE_SYSTEM_MENUBAR; break; case ui::AX_ROLE_MENU_ITEM: - ia_role_ = ROLE_SYSTEM_MENUITEM; + ia_role = ROLE_SYSTEM_MENUITEM; break; case ui::AX_ROLE_MENU_ITEM_CHECK_BOX: - ia_role_ = ROLE_SYSTEM_MENUITEM; - ia2_role_ = IA2_ROLE_CHECK_MENU_ITEM; - ia2_state_ |= IA2_STATE_CHECKABLE; + ia_role = ROLE_SYSTEM_MENUITEM; + ia2_role = IA2_ROLE_CHECK_MENU_ITEM; + ia2_state |= IA2_STATE_CHECKABLE; break; case ui::AX_ROLE_MENU_ITEM_RADIO: - ia_role_ = ROLE_SYSTEM_MENUITEM; - ia2_role_ = IA2_ROLE_RADIO_MENU_ITEM; + ia_role = ROLE_SYSTEM_MENUITEM; + ia2_role = IA2_ROLE_RADIO_MENU_ITEM; break; case ui::AX_ROLE_MENU_LIST_POPUP: - ia_role_ = ROLE_SYSTEM_CLIENT; + ia_role = ROLE_SYSTEM_CLIENT; break; case ui::AX_ROLE_MENU_LIST_OPTION: - ia_role_ = ROLE_SYSTEM_LISTITEM; - if (ia_state_ & STATE_SYSTEM_SELECTABLE) { - ia_state_ |= STATE_SYSTEM_FOCUSABLE; + ia_role = ROLE_SYSTEM_LISTITEM; + if (ia_state & STATE_SYSTEM_SELECTABLE) { + ia_state |= STATE_SYSTEM_FOCUSABLE; if (HasState(ui::AX_STATE_FOCUSED)) - ia_state_ |= STATE_SYSTEM_FOCUSED; + ia_state |= STATE_SYSTEM_FOCUSED; } break; case ui::AX_ROLE_METER: - role_name_ = html_tag; - ia_role_ = ROLE_SYSTEM_PROGRESSBAR; + role_name = html_tag; + ia_role = ROLE_SYSTEM_PROGRESSBAR; break; case ui::AX_ROLE_NAVIGATION: - ia_role_ = ROLE_SYSTEM_GROUPING; - ia2_role_ = IA2_ROLE_SECTION; + ia_role = ROLE_SYSTEM_GROUPING; + ia2_role = IA2_ROLE_SECTION; break; case ui::AX_ROLE_NOTE: - ia_role_ = ROLE_SYSTEM_GROUPING; - ia2_role_ = IA2_ROLE_NOTE; + ia_role = ROLE_SYSTEM_GROUPING; + ia2_role = IA2_ROLE_NOTE; break; case ui::AX_ROLE_OUTLINE: - ia_role_ = ROLE_SYSTEM_OUTLINE; + ia_role = ROLE_SYSTEM_OUTLINE; break; case ui::AX_ROLE_PARAGRAPH: - role_name_ = L"P"; - ia2_role_ = IA2_ROLE_PARAGRAPH; + role_name = L"P"; + ia2_role = IA2_ROLE_PARAGRAPH; break; case ui::AX_ROLE_POP_UP_BUTTON: if (html_tag == L"select") { - ia_role_ = ROLE_SYSTEM_COMBOBOX; + ia_role = ROLE_SYSTEM_COMBOBOX; } else { - ia_role_ = ROLE_SYSTEM_BUTTONMENU; + ia_role = ROLE_SYSTEM_BUTTONMENU; } break; case ui::AX_ROLE_PRE: - role_name_ = html_tag; - ia_role_ = ROLE_SYSTEM_TEXT; - ia2_role_ = IA2_ROLE_PARAGRAPH; + role_name = html_tag; + ia_role = ROLE_SYSTEM_TEXT; + ia2_role = IA2_ROLE_PARAGRAPH; break; case ui::AX_ROLE_PROGRESS_INDICATOR: - ia_role_ = ROLE_SYSTEM_PROGRESSBAR; - ia_state_ |= STATE_SYSTEM_READONLY; + ia_role = ROLE_SYSTEM_PROGRESSBAR; + ia_state |= STATE_SYSTEM_READONLY; break; case ui::AX_ROLE_RADIO_BUTTON: - ia_role_ = ROLE_SYSTEM_RADIOBUTTON; - ia2_state_ = IA2_STATE_CHECKABLE; + ia_role = ROLE_SYSTEM_RADIOBUTTON; + ia2_state = IA2_STATE_CHECKABLE; break; case ui::AX_ROLE_RADIO_GROUP: - ia_role_ = ROLE_SYSTEM_GROUPING; + ia_role = ROLE_SYSTEM_GROUPING; break; case ui::AX_ROLE_REGION: if (html_tag == L"section") { - ia_role_ = ROLE_SYSTEM_GROUPING; - ia2_role_ = IA2_ROLE_SECTION; + ia_role = ROLE_SYSTEM_GROUPING; + ia2_role = IA2_ROLE_SECTION; } else { - ia_role_ = ROLE_SYSTEM_PANE; + ia_role = ROLE_SYSTEM_PANE; } break; case ui::AX_ROLE_ROW: - ia_role_ = ROLE_SYSTEM_ROW; + ia_role = ROLE_SYSTEM_ROW; break; case ui::AX_ROLE_ROW_HEADER: - ia_role_ = ROLE_SYSTEM_ROWHEADER; + ia_role = ROLE_SYSTEM_ROWHEADER; break; case ui::AX_ROLE_RUBY: - ia_role_ = ROLE_SYSTEM_TEXT; - ia2_role_ = IA2_ROLE_TEXT_FRAME; + ia_role = ROLE_SYSTEM_TEXT; + ia2_role = IA2_ROLE_TEXT_FRAME; break; case ui::AX_ROLE_RULER: - ia_role_ = ROLE_SYSTEM_CLIENT; - ia2_role_ = IA2_ROLE_RULER; - ia_state_ |= STATE_SYSTEM_READONLY; + ia_role = ROLE_SYSTEM_CLIENT; + ia2_role = IA2_ROLE_RULER; + ia_state |= STATE_SYSTEM_READONLY; break; case ui::AX_ROLE_SCROLL_AREA: - ia_role_ = ROLE_SYSTEM_CLIENT; - ia2_role_ = IA2_ROLE_SCROLL_PANE; - ia_state_ |= STATE_SYSTEM_READONLY; - ia2_state_ &= ~(IA2_STATE_EDITABLE); + ia_role = ROLE_SYSTEM_CLIENT; + ia2_role = IA2_ROLE_SCROLL_PANE; + ia_state |= STATE_SYSTEM_READONLY; + ia2_state &= ~(IA2_STATE_EDITABLE); break; case ui::AX_ROLE_SCROLL_BAR: - ia_role_ = ROLE_SYSTEM_SCROLLBAR; + ia_role = ROLE_SYSTEM_SCROLLBAR; break; case ui::AX_ROLE_SLIDER: - ia_role_ = ROLE_SYSTEM_SLIDER; + ia_role = ROLE_SYSTEM_SLIDER; break; case ui::AX_ROLE_SPIN_BUTTON: - ia_role_ = ROLE_SYSTEM_SPINBUTTON; + ia_role = ROLE_SYSTEM_SPINBUTTON; break; case ui::AX_ROLE_SPIN_BUTTON_PART: - ia_role_ = ROLE_SYSTEM_PUSHBUTTON; + ia_role = ROLE_SYSTEM_PUSHBUTTON; break; case ui::AX_ROLE_ANNOTATION: case ui::AX_ROLE_LIST_MARKER: case ui::AX_ROLE_STATIC_TEXT: - ia_role_ = ROLE_SYSTEM_STATICTEXT; + ia_role = ROLE_SYSTEM_STATICTEXT; break; case ui::AX_ROLE_STATUS: - ia_role_ = ROLE_SYSTEM_STATUSBAR; + ia_role = ROLE_SYSTEM_STATUSBAR; break; case ui::AX_ROLE_SPLITTER: - ia_role_ = ROLE_SYSTEM_SEPARATOR; + ia_role = ROLE_SYSTEM_SEPARATOR; break; case ui::AX_ROLE_SVG_ROOT: - ia_role_ = ROLE_SYSTEM_GRAPHIC; + ia_role = ROLE_SYSTEM_GRAPHIC; break; case ui::AX_ROLE_TAB: - ia_role_ = ROLE_SYSTEM_PAGETAB; + ia_role = ROLE_SYSTEM_PAGETAB; break; case ui::AX_ROLE_TABLE: { base::string16 aria_role = GetString16Attribute( ui::AX_ATTR_ROLE); if (aria_role == L"treegrid") { - ia_role_ = ROLE_SYSTEM_OUTLINE; + ia_role = ROLE_SYSTEM_OUTLINE; } else { - ia_role_ = ROLE_SYSTEM_TABLE; + ia_role = ROLE_SYSTEM_TABLE; } break; } case ui::AX_ROLE_TABLE_HEADER_CONTAINER: - ia_role_ = ROLE_SYSTEM_GROUPING; - ia2_role_ = IA2_ROLE_SECTION; - ia_state_ |= STATE_SYSTEM_READONLY; + ia_role = ROLE_SYSTEM_GROUPING; + ia2_role = IA2_ROLE_SECTION; + ia_state |= STATE_SYSTEM_READONLY; break; case ui::AX_ROLE_TAB_LIST: - ia_role_ = ROLE_SYSTEM_PAGETABLIST; + ia_role = ROLE_SYSTEM_PAGETABLIST; break; case ui::AX_ROLE_TAB_PANEL: - ia_role_ = ROLE_SYSTEM_PROPERTYPAGE; + ia_role = ROLE_SYSTEM_PROPERTYPAGE; break; case ui::AX_ROLE_TOGGLE_BUTTON: - ia_role_ = ROLE_SYSTEM_PUSHBUTTON; - ia2_role_ = IA2_ROLE_TOGGLE_BUTTON; + ia_role = ROLE_SYSTEM_PUSHBUTTON; + ia2_role = IA2_ROLE_TOGGLE_BUTTON; break; case ui::AX_ROLE_TEXT_AREA: - ia_role_ = ROLE_SYSTEM_TEXT; - ia2_state_ |= IA2_STATE_MULTI_LINE; - ia2_state_ |= IA2_STATE_EDITABLE; - ia2_state_ |= IA2_STATE_SELECTABLE_TEXT; + ia_role = ROLE_SYSTEM_TEXT; + ia2_state |= IA2_STATE_MULTI_LINE; + ia2_state |= IA2_STATE_EDITABLE; + ia2_state |= IA2_STATE_SELECTABLE_TEXT; break; case ui::AX_ROLE_TEXT_FIELD: - ia_role_ = ROLE_SYSTEM_TEXT; - ia2_state_ |= IA2_STATE_SINGLE_LINE; - ia2_state_ |= IA2_STATE_EDITABLE; - ia2_state_ |= IA2_STATE_SELECTABLE_TEXT; + ia_role = ROLE_SYSTEM_TEXT; + ia2_state |= IA2_STATE_SINGLE_LINE; + ia2_state |= IA2_STATE_EDITABLE; + ia2_state |= IA2_STATE_SELECTABLE_TEXT; break; case ui::AX_ROLE_TIME: - ia_role_ = ROLE_SYSTEM_SPINBUTTON; + ia_role = ROLE_SYSTEM_SPINBUTTON; break; case ui::AX_ROLE_TIMER: - ia_role_ = ROLE_SYSTEM_CLOCK; - ia_state_ |= STATE_SYSTEM_READONLY; + ia_role = ROLE_SYSTEM_CLOCK; + ia_state |= STATE_SYSTEM_READONLY; break; case ui::AX_ROLE_TOOLBAR: - ia_role_ = ROLE_SYSTEM_TOOLBAR; - ia_state_ |= STATE_SYSTEM_READONLY; + ia_role = ROLE_SYSTEM_TOOLBAR; + ia_state |= STATE_SYSTEM_READONLY; break; case ui::AX_ROLE_TOOLTIP: - ia_role_ = ROLE_SYSTEM_TOOLTIP; - ia_state_ |= STATE_SYSTEM_READONLY; + ia_role = ROLE_SYSTEM_TOOLTIP; + ia_state |= STATE_SYSTEM_READONLY; break; case ui::AX_ROLE_TREE: - ia_role_ = ROLE_SYSTEM_OUTLINE; + ia_role = ROLE_SYSTEM_OUTLINE; break; case ui::AX_ROLE_TREE_GRID: - ia_role_ = ROLE_SYSTEM_OUTLINE; + ia_role = ROLE_SYSTEM_OUTLINE; break; case ui::AX_ROLE_TREE_ITEM: - ia_role_ = ROLE_SYSTEM_OUTLINEITEM; + ia_role = ROLE_SYSTEM_OUTLINEITEM; break; case ui::AX_ROLE_LINE_BREAK: - ia_role_ = ROLE_SYSTEM_WHITESPACE; + ia_role = ROLE_SYSTEM_WHITESPACE; break; case ui::AX_ROLE_WINDOW: - ia_role_ = ROLE_SYSTEM_WINDOW; + ia_role = ROLE_SYSTEM_WINDOW; break; // TODO(dmazzoni): figure out the proper MSAA role for all of these. @@ -3870,7 +4009,7 @@ case ui::AX_ROLE_PRESENTATIONAL: case ui::AX_ROLE_SLIDER_THUMB: default: - ia_role_ = ROLE_SYSTEM_CLIENT; + ia_role = ROLE_SYSTEM_CLIENT; break; } @@ -3881,21 +4020,27 @@ // We clear the READONLY state on focusable controls and on a document. // Everything else, the majority of objects, do not have this state set. if (HasState(ui::AX_STATE_FOCUSABLE) && - ia_role_ != ROLE_SYSTEM_DOCUMENT) { - ia_state_ &= ~(STATE_SYSTEM_READONLY); + ia_role != ROLE_SYSTEM_DOCUMENT) { + ia_state &= ~(STATE_SYSTEM_READONLY); } if (!HasState(ui::AX_STATE_READ_ONLY)) - ia_state_ &= ~(STATE_SYSTEM_READONLY); + ia_state &= ~(STATE_SYSTEM_READONLY); if (GetBoolAttribute(ui::AX_ATTR_ARIA_READONLY)) - ia_state_ |= STATE_SYSTEM_READONLY; + ia_state |= STATE_SYSTEM_READONLY; // The role should always be set. - DCHECK(!role_name_.empty() || ia_role_); + DCHECK(!role_name.empty() || ia_role); // If we didn't explicitly set the IAccessible2 role, make it the same // as the MSAA role. - if (!ia2_role_) - ia2_role_ = ia_role_; + if (!ia2_role) + ia2_role = ia_role; + + win_attributes_->ia_role = ia_role; + win_attributes_->ia_state = ia_state; + win_attributes_->role_name = role_name; + win_attributes_->ia2_role = ia2_role; + win_attributes_->ia2_state = ia2_state; } } // namespace content
diff --git a/content/browser/accessibility/browser_accessibility_win.h b/content/browser/accessibility/browser_accessibility_win.h index cd339d5..305dabaf 100644 --- a/content/browser/accessibility/browser_accessibility_win.h +++ b/content/browser/accessibility/browser_accessibility_win.h
@@ -97,11 +97,15 @@ // like NotifyWinEvent, and as the unique ID for IAccessible2 and ISimpleDOM. LONG unique_id_win() const { return unique_id_win_; } + CONTENT_EXPORT void UpdateIAccessibleText(); + // // BrowserAccessibility methods. // CONTENT_EXPORT virtual void OnDataChanged() override; CONTENT_EXPORT virtual void OnUpdateFinished() override; + CONTENT_EXPORT virtual void OnSubtreeWillBeDeleted() override; + CONTENT_EXPORT virtual void OnSubtreeCreationFinished() override; CONTENT_EXPORT virtual void NativeAddReference() override; CONTENT_EXPORT virtual void NativeReleaseReference() override; CONTENT_EXPORT virtual bool IsNative() const override; @@ -775,14 +779,18 @@ void** object); // Accessors. - int32 ia_role() const { return ia_role_; } - int32 ia_state() const { return ia_state_; } - const base::string16& role_name() const { return role_name_; } - int32 ia2_role() const { return ia2_role_; } - int32 ia2_state() const { return ia2_state_; } + int32 ia_role() const { return win_attributes_->ia_role; } + int32 ia_state() const { return win_attributes_->ia_state; } + const base::string16& role_name() const { return win_attributes_->role_name; } + int32 ia2_role() const { return win_attributes_->ia2_role; } + int32 ia2_state() const { return win_attributes_->ia2_state; } const std::vector<base::string16>& ia2_attributes() const { - return ia2_attributes_; + return win_attributes_->ia2_attributes; } + base::string16 name() const { return win_attributes_->name; } + base::string16 description() const { return win_attributes_->description; } + base::string16 help() const { return win_attributes_->help; } + base::string16 value() const { return win_attributes_->value; } private: // Add one to the reference count and return the same object. Always @@ -823,6 +831,9 @@ void IntAttributeToIA2(ui::AXIntAttribute attribute, const char* ia2_attr); + // Append the accessible name from this node and its children. + base::string16 GetNameRecursive() const; + // Get the value text, which might come from the floating-point // value for some roles. base::string16 GetValueText(); @@ -831,6 +842,9 @@ // be the name, it may be the value, etc. depending on the role. base::string16 TextForIAccessibleText(); + void ComputeHypertextRemovedAndInserted( + int* start, int* old_len, int* new_len); + // If offset is a member of IA2TextSpecialOffsets this function updates the // value of offset and returns, otherwise offset remains unchanged. void HandleSpecialTextOffset(const base::string16& text, LONG* offset); @@ -855,37 +869,40 @@ // IAccessible2 and ISimpleDOM. LONG unique_id_win_; - // IAccessible role and state. - int32 ia_role_; - int32 ia_state_; - base::string16 role_name_; + struct WinAttributes { + WinAttributes(); - // IAccessible2 role and state. - int32 ia2_role_; - int32 ia2_state_; + // IAccessible role and state. + int32 ia_role; + int32 ia_state; + base::string16 role_name; - // IAccessible2 attributes. - std::vector<base::string16> ia2_attributes_; + // IAccessible name, description, help, value. + base::string16 name; + base::string16 description; + base::string16 help; + base::string16 value; - // True in Initialize when the object is first created, and false - // subsequent times. - bool first_time_; + // IAccessible2 role and state. + int32 ia2_role; + int32 ia2_state; - // The previous text, before the last update to this object. - base::string16 previous_text_; + // IAccessible2 attributes. + std::vector<base::string16> ia2_attributes; + }; - // The old text to return in IAccessibleText::get_oldText - this is like - // previous_text_ except that it's NOT updated when the object - // is initialized again but the text doesn't change. - base::string16 old_text_; + scoped_ptr<WinAttributes> win_attributes_; - // The previous state, used to see if there was a state change. - int32 old_ia_state_; + // Only valid during the scope of a IA2_EVENT_TEXT_REMOVED or + // IA2_EVENT_TEXT_INSERTED event. + scoped_ptr<WinAttributes> old_win_attributes_; // Relationships between this node and other nodes. std::vector<BrowserAccessibilityRelation*> relations_; - // The text of this node including embedded hyperlink characters. + // IAccessibleText text of this node including + // embedded hyperlink characters. + base::string16 old_hypertext_; base::string16 hypertext_; // Maps the |hypertext_| embedded character offset to an index in
diff --git a/content/browser/accessibility/dump_accessibility_events_browsertest.cc b/content/browser/accessibility/dump_accessibility_events_browsertest.cc index 822f920..5247dd9 100644 --- a/content/browser/accessibility/dump_accessibility_events_browsertest.cc +++ b/content/browser/accessibility/dump_accessibility_events_browsertest.cc
@@ -154,27 +154,23 @@ RunEventTest(FILE_PATH_LITERAL("add-alert.html")); } -// http://crbug.com/447962 - change that makes this test pass will land soon. IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest, - DISABLED_AccessibilityEventsAddChild) { + AccessibilityEventsAddChild) { RunEventTest(FILE_PATH_LITERAL("add-child.html")); } -// http://crbug.com/447962 - change that makes this test pass will land soon. IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest, - DISABLED_AccessibilityEventsAddHiddenAttribute) { + AccessibilityEventsAddHiddenAttribute) { RunEventTest(FILE_PATH_LITERAL("add-hidden-attribute.html")); } -// http://crbug.com/447962 - change that makes this test pass will land soon. IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest, - DISABLED_AccessibilityEventsAddHiddenAttributeSubtree) { + AccessibilityEventsAddHiddenAttributeSubtree) { RunEventTest(FILE_PATH_LITERAL("add-hidden-attribute-subtree.html")); } -// http://crbug.com/447962 - change that makes this test pass will land soon. IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest, - DISABLED_AccessibilityEventsAddSubtree) { + AccessibilityEventsAddSubtree) { RunEventTest(FILE_PATH_LITERAL("add-subtree.html")); } @@ -183,21 +179,18 @@ RunEventTest(FILE_PATH_LITERAL("checked-state-changed.html")); } -// http://crbug.com/447962 - change that makes this test pass will land soon. IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest, - DISABLED_AccessibilityEventsCSSDisplay) { + AccessibilityEventsCSSDisplay) { RunEventTest(FILE_PATH_LITERAL("css-display.html")); } -// http://crbug.com/447962 - change that makes this test pass will land soon. IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest, - DISABLED_AccessibilityEventsCSSVisibility) { + AccessibilityEventsCSSVisibility) { RunEventTest(FILE_PATH_LITERAL("css-visibility.html")); } -// http://crbug.com/447962 - change that makes this test pass will land soon. IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest, - DISABLED_AccessibilityEventsDescriptionChange) { + AccessibilityEventsDescriptionChange) { RunEventTest(FILE_PATH_LITERAL("description-change.html")); } @@ -211,34 +204,29 @@ RunEventTest(FILE_PATH_LITERAL("name-change.html")); } -// http://crbug.com/447962 - change that makes this test pass will land soon. IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest, - DISABLED_AccessibilityEventsRemoveChild) { + AccessibilityEventsRemoveChild) { RunEventTest(FILE_PATH_LITERAL("remove-child.html")); } -// http://crbug.com/447962 - change that makes this test pass will land soon. IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest, - DISABLED_AccessibilityEventsRemoveHiddenAttribute) { + AccessibilityEventsRemoveHiddenAttribute) { RunEventTest(FILE_PATH_LITERAL("remove-hidden-attribute.html")); } -// http://crbug.com/447962 - change that makes this test pass will land soon. IN_PROC_BROWSER_TEST_F( DumpAccessibilityEventsTest, - DISABLED_AccessibilityEventsRemoveHiddenAttributeSubtree) { + AccessibilityEventsRemoveHiddenAttributeSubtree) { RunEventTest(FILE_PATH_LITERAL("remove-hidden-attribute-subtree.html")); } -// http://crbug.com/447962 - change that makes this test pass will land soon. IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest, - DISABLED_AccessibilityEventsRemoveSubtree) { + AccessibilityEventsRemoveSubtree) { RunEventTest(FILE_PATH_LITERAL("remove-subtree.html")); } -// http://crbug.com/447962 - change that makes this test pass will land soon. IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest, - DISABLED_AccessibilityEventsTextChanged) { + AccessibilityEventsTextChanged) { RunEventTest(FILE_PATH_LITERAL("text-changed.html")); }
diff --git a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc index 5ce4cc61..a3f60fa3 100644 --- a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc +++ b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -124,8 +124,7 @@ RunHtmlTest(FILE_PATH_LITERAL("a-name-calc.html")); } -IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, - MAYBE(AccessibilityANoText)) { +IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityANoText) { RunHtmlTest(FILE_PATH_LITERAL("a-no-text.html")); } @@ -185,8 +184,10 @@ RunAriaTest(FILE_PATH_LITERAL("aria-checked.html")); } +// crbug.com/451047 will cause new elements to be added to the blink a11y tree +// Re-baseline after the Blink change goes in IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, - AccessibilityAriaColumnHeader) { + DISABLED_AccessibilityAriaColumnHeader) { RunAriaTest(FILE_PATH_LITERAL("aria-columnheader.html")); } @@ -434,7 +435,10 @@ RunAriaTest(FILE_PATH_LITERAL("aria-required.html")); } -IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaRow) { +// crbug.com/451047 will cause new elements to be added to the blink a11y tree +// Re-baseline after the Blink change goes in +IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, + DISABLED_AccessibilityAriaRow) { RunAriaTest(FILE_PATH_LITERAL("aria-row.html")); } @@ -442,7 +446,10 @@ RunAriaTest(FILE_PATH_LITERAL("aria-rowgroup.html")); } -IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaRowHeader) { +// crbug.com/451047 will cause new elements to be added to the blink a11y tree +// Re-baseline after the Blink change goes in +IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, + DISABLED_AccessibilityAriaRowHeader) { RunAriaTest(FILE_PATH_LITERAL("aria-rowheader.html")); } @@ -462,7 +469,10 @@ RunAriaTest(FILE_PATH_LITERAL("aria-separator.html")); } -IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaSort) { +// crbug.com/451047 will cause new elements to be added to the blink a11y tree +// Re-baseline after the Blink change goes in +IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, + DISABLED_AccessibilityAriaSort) { RunAriaTest(FILE_PATH_LITERAL("aria-sort.html")); }
diff --git a/content/browser/accessibility/site_per_process_accessibility_browsertest.cc b/content/browser/accessibility/site_per_process_accessibility_browsertest.cc index 6daf5ab..a10959e1 100644 --- a/content/browser/accessibility/site_per_process_accessibility_browsertest.cc +++ b/content/browser/accessibility/site_per_process_accessibility_browsertest.cc
@@ -4,6 +4,7 @@ #include "base/command_line.h" #include "base/strings/stringprintf.h" +#include "base/strings/utf_string_conversions.h" #include "content/browser/accessibility/browser_accessibility.h" #include "content/browser/accessibility/browser_accessibility_manager.h" #include "content/browser/accessibility/browser_accessibility_state_impl.h" @@ -146,7 +147,8 @@ ax_scroll_area->PlatformGetChild(0); EXPECT_EQ(ui::AX_ROLE_ROOT_WEB_AREA, ax_child_frame_root->GetRole()); ASSERT_EQ(1U, ax_child_frame_root->PlatformChildCount()); - EXPECT_EQ("Title Of Awesomeness", ax_child_frame_root->name()); + EXPECT_EQ("Title Of Awesomeness", + ax_child_frame_root->GetStringAttribute(ui::AX_ATTR_NAME)); BrowserAccessibility* ax_child_frame_group = ax_child_frame_root->PlatformGetChild(0);
diff --git a/content/browser/android/content_view_render_view.cc b/content/browser/android/content_view_render_view.cc index e658041..eb6a695 100644 --- a/content/browser/android/content_view_render_view.cc +++ b/content/browser/android/content_view_render_view.cc
@@ -15,7 +15,6 @@ #include "content/browser/android/content_view_core_impl.h" #include "content/public/browser/android/compositor.h" #include "content/public/browser/android/content_view_layer_renderer.h" -#include "content/public/browser/android/layer_tree_build_helper.h" #include "jni/ContentViewRenderView_jni.h" #include "ui/gfx/android/java_bitmap.h" #include "ui/gfx/geometry/size.h" @@ -27,24 +26,6 @@ namespace content { -namespace { - -class LayerTreeBuildHelperImpl : public LayerTreeBuildHelper { - public: - LayerTreeBuildHelperImpl() {} - virtual ~LayerTreeBuildHelperImpl() {} - - virtual scoped_refptr<cc::Layer> GetLayerTree( - scoped_refptr<cc::Layer> content_root_layer) override { - return content_root_layer; - } - - private: - DISALLOW_COPY_AND_ASSIGN(LayerTreeBuildHelperImpl); -}; - -} // anonymous namespace - // static bool ContentViewRenderView::RegisterContentViewRenderView(JNIEnv* env) { return RegisterNativesImpl(env); @@ -53,25 +34,13 @@ ContentViewRenderView::ContentViewRenderView(JNIEnv* env, jobject obj, gfx::NativeWindow root_window) - : layer_tree_build_helper_(new LayerTreeBuildHelperImpl()), - root_window_(root_window), - current_surface_format_(0) { + : root_window_(root_window), current_surface_format_(0) { java_obj_.Reset(env, obj); } ContentViewRenderView::~ContentViewRenderView() { } -void ContentViewRenderView::SetLayerTreeBuildHelper(JNIEnv* env, - jobject obj, - jlong native_build_helper) { - CHECK(native_build_helper); - - LayerTreeBuildHelper* build_helper = - reinterpret_cast<LayerTreeBuildHelper*>(native_build_helper); - layer_tree_build_helper_.reset(build_helper); - InitCompositor(); -} // static static jlong Init(JNIEnv* env, jobject obj, @@ -92,10 +61,8 @@ InitCompositor(); ContentViewCoreImpl* content_view_core = reinterpret_cast<ContentViewCoreImpl*>(native_content_view_core); - compositor_->SetRootLayer(content_view_core - ? layer_tree_build_helper_->GetLayerTree( - content_view_core->GetLayer()) - : scoped_refptr<cc::Layer>()); + compositor_->SetRootLayer(content_view_core ? content_view_core->GetLayer() + : scoped_refptr<cc::Layer>()); } void ContentViewRenderView::SurfaceCreated(
diff --git a/content/browser/android/content_view_render_view.h b/content/browser/android/content_view_render_view.h index ed3f03c..0b09b38 100644 --- a/content/browser/android/content_view_render_view.h +++ b/content/browser/android/content_view_render_view.h
@@ -34,8 +34,6 @@ void Destroy(JNIEnv* env, jobject obj); void SetCurrentContentViewCore(JNIEnv* env, jobject obj, jlong native_content_view_core); - void SetLayerTreeBuildHelper( - JNIEnv* env, jobject obj, jlong native_build_helper); void SurfaceCreated(JNIEnv* env, jobject obj); void SurfaceDestroyed(JNIEnv* env, jobject obj); void SurfaceChanged(JNIEnv* env, jobject obj, @@ -58,7 +56,6 @@ void InitCompositor(); base::android::ScopedJavaGlobalRef<jobject> java_obj_; - scoped_ptr<LayerTreeBuildHelper> layer_tree_build_helper_; scoped_ptr<content::Compositor> compositor_;
diff --git a/content/browser/android/in_process/synchronous_compositor_factory_impl.cc b/content/browser/android/in_process/synchronous_compositor_factory_impl.cc index 0fdf66e..4767b83 100644 --- a/content/browser/android/in_process/synchronous_compositor_factory_impl.cc +++ b/content/browser/android/in_process/synchronous_compositor_factory_impl.cc
@@ -53,7 +53,7 @@ gfx::kNullAcceleratedWidget, gfx::Size(1, 1), NULL /* share_context */, - true, // TODO(sievers): Use attributes.shareResources. crbug/443464. + attributes.shareResources, in_process_attribs, gpu_preference, gpu::GLInProcessContextSharedMemoryLimits(),
diff --git a/content/browser/battery_status/battery_monitor_integration_browsertest.cc b/content/browser/battery_status/battery_monitor_integration_browsertest.cc index 8bf1ca4..541d769 100644 --- a/content/browser/battery_status/battery_monitor_integration_browsertest.cc +++ b/content/browser/battery_status/battery_monitor_integration_browsertest.cc
@@ -16,7 +16,7 @@ #include "content/shell/browser/shell.h" #include "content/shell/browser/shell_content_browser_client.h" #include "device/battery/battery_monitor.mojom.h" -#include "mojo/public/cpp/bindings/strong_binding.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/strong_binding.h" // These tests run against a dummy implementation of the BatteryMonitor service. // That is, they verify that the service implementation is correctly exposed to
diff --git a/content/browser/browser_plugin/browser_plugin_guest.cc b/content/browser/browser_plugin/browser_plugin_guest.cc index 269d4ab..543a63c7 100644 --- a/content/browser/browser_plugin/browser_plugin_guest.cc +++ b/content/browser/browser_plugin/browser_plugin_guest.cc
@@ -354,7 +354,7 @@ 1.0f / frame->metadata.device_scale_factor))); if (last_seen_view_size_ != view_size) { - delegate_->GuestSizeChanged(last_seen_view_size_, view_size); + delegate_->GuestSizeChanged(view_size); last_seen_view_size_ = view_size; }
diff --git a/content/browser/child_process_launcher.cc b/content/browser/child_process_launcher.cc index 0599ffef..fbc1a55 100644 --- a/content/browser/child_process_launcher.cc +++ b/content/browser/child_process_launcher.cc
@@ -440,7 +440,7 @@ } if (process.IsValid()) - broker->AddPlaceholderForPid(process.pid(), child_process_id); + broker->AddPlaceholderForPid(process.Pid(), child_process_id); // After updating the broker, release the lock and let the child's // messasge be processed on the broker's thread.
diff --git a/content/browser/compositor/browser_compositor_output_surface.cc b/content/browser/compositor/browser_compositor_output_surface.cc index 0c650ca..769f44e 100644 --- a/content/browser/compositor/browser_compositor_output_surface.cc +++ b/content/browser/compositor/browser_compositor_output_surface.cc
@@ -13,7 +13,7 @@ namespace content { BrowserCompositorOutputSurface::BrowserCompositorOutputSurface( - const scoped_refptr<ContextProviderCommandBuffer>& context_provider, + const scoped_refptr<cc::ContextProvider>& context_provider, int surface_id, IDMap<BrowserCompositorOutputSurface>* output_surface_map, const scoped_refptr<ui::CompositorVSyncManager>& vsync_manager)
diff --git a/content/browser/compositor/browser_compositor_output_surface.h b/content/browser/compositor/browser_compositor_output_surface.h index 067207e..ed9ca7cd 100644 --- a/content/browser/compositor/browser_compositor_output_surface.h +++ b/content/browser/compositor/browser_compositor_output_surface.h
@@ -48,7 +48,7 @@ protected: // Constructor used by the accelerated implementation. BrowserCompositorOutputSurface( - const scoped_refptr<ContextProviderCommandBuffer>& context, + const scoped_refptr<cc::ContextProvider>& context, int surface_id, IDMap<BrowserCompositorOutputSurface>* output_surface_map, const scoped_refptr<ui::CompositorVSyncManager>& vsync_manager);
diff --git a/content/browser/compositor/buffer_queue.cc b/content/browser/compositor/buffer_queue.cc index c58e6bc16..c215827 100644 --- a/content/browser/compositor/buffer_queue.cc +++ b/content/browser/compositor/buffer_queue.cc
@@ -101,6 +101,9 @@ in_flight_surfaces_.push_back(current_surface_); current_surface_.texture = 0; current_surface_.image = 0; + // Some things reset the framebuffer (CopySubBufferDamage, some GLRenderer + // paths), so ensure we restore it here. + context_provider_->ContextGL()->BindFramebuffer(GL_FRAMEBUFFER, fbo_); } void BufferQueue::Reshape(const gfx::Size& size, float scale_factor) {
diff --git a/content/browser/compositor/buffer_queue.h b/content/browser/compositor/buffer_queue.h index db7fcc5..8905da1 100644 --- a/content/browser/compositor/buffer_queue.h +++ b/content/browser/compositor/buffer_queue.h
@@ -43,7 +43,8 @@ void PageFlipComplete(); void Reshape(const gfx::Size& size, float scale_factor); - unsigned int current_texture_id() { return current_surface_.texture; } + unsigned int current_texture_id() const { return current_surface_.texture; } + unsigned int fbo() const { return fbo_; } private: friend class BufferQueueTest;
diff --git a/content/browser/compositor/buffer_queue_unittest.cc b/content/browser/compositor/buffer_queue_unittest.cc index 8506b58..019474f 100644 --- a/content/browser/compositor/buffer_queue_unittest.cc +++ b/content/browser/compositor/buffer_queue_unittest.cc
@@ -9,6 +9,7 @@ #include "content/browser/compositor/buffer_queue.h" #include "content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.h" #include "content/browser/gpu/browser_gpu_memory_buffer_manager.h" +#include "content/common/gpu/client/gl_helper.h" #include "gpu/GLES2/gl2extchromium.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -221,8 +222,37 @@ output_surface->BindFramebuffer(); } +TEST(BufferQueueStandaloneTest, CheckBoundFramebuffer) { + scoped_ptr<BrowserGpuMemoryBufferManager> gpu_memory_buffer_manager; + scoped_ptr<BufferQueue> output_surface; + scoped_refptr<cc::TestContextProvider> context_provider = + cc::TestContextProvider::Create(cc::TestWebGraphicsContext3D::Create()); + context_provider->BindToCurrentThread(); + gpu_memory_buffer_manager.reset(new StubBrowserGpuMemoryBufferManager); + + scoped_ptr<GLHelper> gl_helper; + gl_helper.reset(new GLHelper(context_provider->ContextGL(), + context_provider->ContextSupport())); + + output_surface.reset(new BufferQueue(context_provider, GL_RGBA, + gl_helper.get(), + gpu_memory_buffer_manager.get(), 1)); + output_surface->Initialize(); + output_surface->Reshape(screen_size, 1.0f); + // Trigger a sub-buffer copy to exercise all paths. + output_surface->BindFramebuffer(); + output_surface->SwapBuffers(screen_rect); + output_surface->PageFlipComplete(); + output_surface->BindFramebuffer(); + output_surface->SwapBuffers(small_damage); + + int current_fbo = 0; + context_provider->ContextGL()->GetIntegerv(GL_FRAMEBUFFER_BINDING, + ¤t_fbo); + EXPECT_EQ(static_cast<int>(output_surface->fbo()), current_fbo); +} + TEST_F(BufferQueueTest, PartialSwapReuse) { - // Check that output_surface_->Reshape(screen_size, 1.0f); ASSERT_TRUE(doublebuffering_); EXPECT_CALL(*output_surface_,
diff --git a/content/browser/compositor/delegated_frame_host.cc b/content/browser/compositor/delegated_frame_host.cc index e09c38e..1d99714 100644 --- a/content/browser/compositor/delegated_frame_host.cc +++ b/content/browser/compositor/delegated_frame_host.cc
@@ -53,32 +53,11 @@ } // namespace //////////////////////////////////////////////////////////////////////////////// -// DelegatedFrameHostClient - -bool DelegatedFrameHostClient::ShouldCreateResizeLock() { - // On Windows and Linux, holding pointer moves will not help throttling - // resizes. - // TODO(piman): on Windows we need to block (nested message loop?) the - // WM_SIZE event. On Linux we need to throttle at the WM level using - // _NET_WM_SYNC_REQUEST. - // TODO(ccameron): Mac browser window resizing is incompletely implemented. -#if !defined(OS_CHROMEOS) - return false; -#else - return GetDelegatedFrameHost()->ShouldCreateResizeLock(); -#endif -} - -void DelegatedFrameHostClient::RequestCopyOfOutput( - scoped_ptr<cc::CopyOutputRequest> request) { - GetDelegatedFrameHost()->RequestCopyOfOutput(request.Pass()); -} - -//////////////////////////////////////////////////////////////////////////////// // DelegatedFrameHost DelegatedFrameHost::DelegatedFrameHost(DelegatedFrameHostClient* client) : client_(client), + compositor_(nullptr), use_surfaces_(UseSurfacesEnabled()), last_output_surface_id_(0), pending_delegated_ack_count_(0), @@ -94,14 +73,12 @@ if (surface_id_.is_null() && !frame_provider_.get() && !released_front_lock_.get()) { - ui::Compositor* compositor = client_->GetCompositor(); - if (compositor) - released_front_lock_ = compositor->GetCompositorLock(); + if (compositor_) + released_front_lock_ = compositor_->GetCompositorLock(); } - ui::Compositor* compositor = client_->GetCompositor(); - if (compositor) { - compositor->SetLatencyInfo(latency_info); + if (compositor_) { + compositor_->SetLatencyInfo(latency_info); } } @@ -115,14 +92,9 @@ } void DelegatedFrameHost::MaybeCreateResizeLock() { - if (!client_->ShouldCreateResizeLock()) + if (!ShouldCreateResizeLock()) return; - DCHECK(client_->GetCompositor()); - - // Listen to changes in the compositor lock state. - ui::Compositor* compositor = client_->GetCompositor(); - if (!compositor->HasObserver(this)) - compositor->AddObserver(this); + DCHECK(compositor_); bool defer_compositor_lock = can_lock_compositor_ == NO_PENDING_RENDERER_FRAME || @@ -131,34 +103,27 @@ if (can_lock_compositor_ == YES_CAN_LOCK) can_lock_compositor_ = YES_DID_LOCK; - resize_lock_ = client_->CreateResizeLock(defer_compositor_lock); + resize_lock_ = + client_->DelegatedFrameHostCreateResizeLock(defer_compositor_lock); } bool DelegatedFrameHost::ShouldCreateResizeLock() { - RenderWidgetHostImpl* host = client_->GetHost(); + if (!client_->DelegatedFrameCanCreateResizeLock()) + return false; if (resize_lock_) return false; - if (host->auto_resize_enabled()) - return false; - - gfx::Size desired_size = client_->DesiredFrameSize(); + gfx::Size desired_size = client_->DelegatedFrameHostDesiredSizeInDIP(); if (desired_size == current_frame_size_in_dip_ || desired_size.IsEmpty()) return false; - ui::Compositor* compositor = client_->GetCompositor(); - if (!compositor) + if (!compositor_) return false; return true; } -void DelegatedFrameHost::RequestCopyOfOutput( - scoped_ptr<cc::CopyOutputRequest> request) { - client_->GetLayer()->RequestCopyOfOutput(request.Pass()); -} - void DelegatedFrameHost::CopyFromCompositingSurface( const gfx::Rect& src_subrect, const gfx::Size& output_size, @@ -182,7 +147,7 @@ callback)); if (!src_subrect.IsEmpty()) request->set_area(src_subrect); - client_->RequestCopyOfOutput(request.Pass()); + RequestCopyOfOutput(request.Pass()); } void DelegatedFrameHost::CopyFromCompositingSurfaceToVideoFrame( @@ -221,17 +186,17 @@ subscriber_texture->target(), subscriber_texture->sync_point())); } - client_->RequestCopyOfOutput(request.Pass()); + RequestCopyOfOutput(request.Pass()); } bool DelegatedFrameHost::CanCopyToBitmap() const { - return client_->GetCompositor() && - client_->GetLayer()->has_external_content(); + return compositor_ && + client_->DelegatedFrameHostGetLayer()->has_external_content(); } bool DelegatedFrameHost::CanCopyToVideoFrame() const { - return client_->GetCompositor() && - client_->GetLayer()->has_external_content(); + return compositor_ && + client_->DelegatedFrameHostGetLayer()->has_external_content(); } bool DelegatedFrameHost::CanSubscribeFrame() const { @@ -261,8 +226,9 @@ } void DelegatedFrameHost::WasResized() { - if (client_->DesiredFrameSize() != current_frame_size_in_dip_ && - client_->GetHost()->is_hidden()) + if (client_->DelegatedFrameHostDesiredSizeInDIP() != + current_frame_size_in_dip_ && + !client_->DelegatedFrameHostIsVisible()) EvictDelegatedFrame(); MaybeCreateResizeLock(); } @@ -271,7 +237,7 @@ if (resize_lock_) return resize_lock_->expected_size(); else - return client_->DesiredFrameSize(); + return client_->DelegatedFrameHostDesiredSizeInDIP(); } void DelegatedFrameHost::CheckResizeLock() { @@ -283,11 +249,6 @@ // the release of the lock until we've kicked a frame with the new texture, to // avoid resizing the UI before we have a chance to draw a "good" frame. resize_lock_->UnlockCompositor(); - ui::Compositor* compositor = client_->GetCompositor(); - if (compositor) { - if (!compositor->HasObserver(this)) - compositor->AddObserver(this); - } } void DelegatedFrameHost::DidReceiveFrameFromRenderer( @@ -320,7 +281,6 @@ scoped_ptr<cc::DelegatedFrameData> frame_data, float frame_device_scale_factor, const std::vector<ui::LatencyInfo>& latency_info) { - RenderWidgetHostImpl* host = client_->GetHost(); DCHECK(!frame_data->render_pass_list.empty()); cc::RenderPass* root_pass = frame_data->render_pass_list.back(); @@ -342,9 +302,7 @@ skipped_latency_info_list_.insert(skipped_latency_info_list_.end(), latency_info.begin(), latency_info.end()); - RenderWidgetHostImpl::SendSwapCompositorFrameAck( - host->GetRoutingID(), output_surface_id, - host->GetProcess()->GetID(), ack); + client_->DelegatedFrameHostSendCompositorSwapAck(output_surface_id, ack); skipped_frames_ = true; return; } @@ -385,8 +343,9 @@ } last_output_surface_id_ = output_surface_id; } - ui::Compositor* compositor = client_->GetCompositor(); - bool immediate_ack = !compositor; + bool immediate_ack = !compositor_; + pending_delegated_ack_count_++; + if (frame_size.IsEmpty()) { DCHECK(frame_data->resource_list.empty()); EvictDelegatedFrame(); @@ -407,7 +366,7 @@ surface_id_ = id_allocator_->GenerateId(); surface_factory_->Create(surface_id_); // manager must outlive compositors using it. - client_->GetLayer()->SetShowSurface( + client_->DelegatedFrameHostGetLayer()->SetShowSurface( surface_id_, base::Bind(&SatisfyCallback, base::Unretained(manager)), base::Bind(&RequireCallback, base::Unretained(manager)), frame_size, @@ -425,12 +384,12 @@ latency_info.begin(), latency_info.end()); - gfx::Size desired_size = client_->DesiredFrameSize(); + gfx::Size desired_size = client_->DelegatedFrameHostDesiredSizeInDIP(); if (desired_size != frame_size_in_dip && !desired_size.IsEmpty()) immediate_ack = true; cc::SurfaceFactory::DrawCallback ack_callback; - if (compositor && !immediate_ack) { + if (compositor_ && !immediate_ack) { ack_callback = base::Bind(&DelegatedFrameHost::SurfaceDrawn, AsWeakPtr(), output_surface_id); } @@ -451,8 +410,8 @@ frame_size_in_dip != current_frame_size_in_dip_) { frame_provider_ = new cc::DelegatedFrameProvider( resource_collection_.get(), frame_data.Pass()); - client_->GetLayer()->SetShowDelegatedContent(frame_provider_.get(), - frame_size_in_dip); + client_->DelegatedFrameHostGetLayer()->SetShowDelegatedContent( + frame_provider_.get(), frame_size_in_dip); } else { frame_provider_->SetFrameData(frame_data.Pass()); } @@ -463,21 +422,20 @@ CheckResizeLock(); if (!damage_rect_in_dip.IsEmpty()) - client_->GetLayer()->OnDelegatedFrameDamage(damage_rect_in_dip); - - pending_delegated_ack_count_++; + client_->DelegatedFrameHostGetLayer()->OnDelegatedFrameDamage( + damage_rect_in_dip); if (immediate_ack) { SendDelegatedFrameAck(output_surface_id); } else if (!use_surfaces_) { std::vector<ui::LatencyInfo>::const_iterator it; for (it = latency_info.begin(); it != latency_info.end(); ++it) - compositor->SetLatencyInfo(*it); + compositor_->SetLatencyInfo(*it); // If we've previously skipped any latency infos add them. for (it = skipped_latency_info_list_.begin(); it != skipped_latency_info_list_.end(); ++it) - compositor->SetLatencyInfo(*it); + compositor_->SetLatencyInfo(*it); skipped_latency_info_list_.clear(); AddOnCommitCallbackAndDisableLocks( base::Bind(&DelegatedFrameHost::SendDelegatedFrameAck, @@ -488,26 +446,24 @@ } DidReceiveFrameFromRenderer(damage_rect); if (frame_provider_.get() || !surface_id_.is_null()) - delegated_frame_evictor_->SwappedFrame(!host->is_hidden()); + delegated_frame_evictor_->SwappedFrame( + client_->DelegatedFrameHostIsVisible()); // Note: the frame may have been evicted immediately. } void DelegatedFrameHost::SendDelegatedFrameAck(uint32 output_surface_id) { - RenderWidgetHostImpl* host = client_->GetHost(); cc::CompositorFrameAck ack; if (!surface_returned_resources_.empty()) ack.resources.swap(surface_returned_resources_); if (resource_collection_.get()) resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources); - RenderWidgetHostImpl::SendSwapCompositorFrameAck(host->GetRoutingID(), - output_surface_id, - host->GetProcess()->GetID(), - ack); + client_->DelegatedFrameHostSendCompositorSwapAck(output_surface_id, ack); DCHECK_GT(pending_delegated_ack_count_, 0); pending_delegated_ack_count_--; } -void DelegatedFrameHost::SurfaceDrawn(uint32 output_surface_id, bool drawn) { +void DelegatedFrameHost::SurfaceDrawn(uint32 output_surface_id, + cc::SurfaceDrawStatus drawn) { SendDelegatedFrameAck(output_surface_id); } @@ -520,8 +476,6 @@ void DelegatedFrameHost::SendReturnedDelegatedResources( uint32 output_surface_id) { - RenderWidgetHostImpl* host = client_->GetHost(); - cc::CompositorFrameAck ack; if (!surface_returned_resources_.empty()) { ack.resources.swap(surface_returned_resources_); @@ -531,11 +485,8 @@ } DCHECK(!ack.resources.empty()); - RenderWidgetHostImpl::SendReclaimCompositorResources( - host->GetRoutingID(), - output_surface_id, - host->GetProcess()->GetID(), - ack); + client_->DelegatedFrameHostSendReclaimCompositorResources(output_surface_id, + ack); } void DelegatedFrameHost::ReturnResources( @@ -550,7 +501,7 @@ } void DelegatedFrameHost::EvictDelegatedFrame() { - client_->GetLayer()->SetShowSolidColorContent(); + client_->DelegatedFrameHostGetLayer()->SetShowSolidColorContent(); frame_provider_ = NULL; if (!surface_id_.is_null()) { surface_factory_->Destroy(surface_id_); @@ -885,7 +836,6 @@ void DelegatedFrameHost::OnCompositingDidCommit( ui::Compositor* compositor) { - RenderWidgetHostImpl* host = client_->GetHost(); if (can_lock_compositor_ == NO_PENDING_COMMIT) { can_lock_compositor_ = YES_CAN_LOCK; if (resize_lock_.get() && resize_lock_->GrabDeferredLock()) @@ -895,7 +845,7 @@ if (resize_lock_ && resize_lock_->expected_size() == current_frame_size_in_dip_) { resize_lock_.reset(); - host->WasResized(); + client_->DelegatedFrameHostResizeLockWasReleased(); // We may have had a resize while we had the lock (e.g. if the lock expired, // or if the UI still gave us some resizes), so make sure we grab a new lock // if necessary. @@ -924,33 +874,38 @@ } } +void DelegatedFrameHost::OnCompositingShuttingDown(ui::Compositor* compositor) { + DCHECK_EQ(compositor, compositor_); + ResetCompositor(); + DCHECK(!compositor_); +} + void DelegatedFrameHost::OnUpdateVSyncParameters( base::TimeTicks timebase, base::TimeDelta interval) { vsync_timebase_ = timebase; vsync_interval_ = interval; - RenderWidgetHostImpl* host = client_->GetHost(); - if (client_->IsVisible()) - host->UpdateVSyncParameters(timebase, interval); + if (client_->DelegatedFrameHostIsVisible()) + client_->DelegatedFrameHostUpdateVSyncParameters(timebase, interval); } //////////////////////////////////////////////////////////////////////////////// -// RenderWidgetHostViewAura, ImageTransportFactoryObserver implementation: +// DelegatedFrameHost, ImageTransportFactoryObserver implementation: void DelegatedFrameHost::OnLostResources() { - RenderWidgetHostImpl* host = client_->GetHost(); if (frame_provider_.get() || !surface_id_.is_null()) EvictDelegatedFrame(); idle_frame_subscriber_textures_.clear(); yuv_readback_pipeline_.reset(); - host->ScheduleComposite(); + client_->DelegatedFrameHostOnLostCompositorResources(); } //////////////////////////////////////////////////////////////////////////////// // DelegatedFrameHost, private: DelegatedFrameHost::~DelegatedFrameHost() { + DCHECK(!compositor_); ImageTransportFactory::GetInstance()->RemoveObserver(this); if (!surface_id_.is_null()) @@ -972,38 +927,39 @@ void DelegatedFrameHost::AddOnCommitCallbackAndDisableLocks( const base::Closure& callback) { - ui::Compositor* compositor = client_->GetCompositor(); - DCHECK(compositor); - - if (!compositor->HasObserver(this)) - compositor->AddObserver(this); + DCHECK(compositor_); can_lock_compositor_ = NO_PENDING_COMMIT; if (!callback.is_null()) on_compositing_did_commit_callbacks_.push_back(callback); } -void DelegatedFrameHost::AddedToWindow() { - ui::Compositor* compositor = client_->GetCompositor(); - if (compositor) { - DCHECK(!vsync_manager_.get()); - vsync_manager_ = compositor->vsync_manager(); - vsync_manager_->AddObserver(this); - } +void DelegatedFrameHost::SetCompositor(ui::Compositor* compositor) { + DCHECK(!compositor_); + if (!compositor) + return; + compositor_ = compositor; + compositor_->AddObserver(this); + DCHECK(!vsync_manager_.get()); + vsync_manager_ = compositor_->vsync_manager(); + vsync_manager_->AddObserver(this); } -void DelegatedFrameHost::RemovingFromWindow() { +void DelegatedFrameHost::ResetCompositor() { + if (!compositor_) + return; RunOnCommitCallbacks(); - resize_lock_.reset(); - client_->GetHost()->WasResized(); - ui::Compositor* compositor = client_->GetCompositor(); - if (compositor && compositor->HasObserver(this)) - compositor->RemoveObserver(this); - + if (resize_lock_) { + resize_lock_.reset(); + client_->DelegatedFrameHostResizeLockWasReleased(); + } + if (compositor_->HasObserver(this)) + compositor_->RemoveObserver(this); if (vsync_manager_.get()) { vsync_manager_->RemoveObserver(this); vsync_manager_ = NULL; } + compositor_ = nullptr; } void DelegatedFrameHost::LockResources() { @@ -1011,6 +967,14 @@ delegated_frame_evictor_->LockFrame(); } +void DelegatedFrameHost::RequestCopyOfOutput( + scoped_ptr<cc::CopyOutputRequest> request) { + if (!request_copy_of_output_callback_for_testing_.is_null()) + request_copy_of_output_callback_for_testing_.Run(request.Pass()); + else + client_->DelegatedFrameHostGetLayer()->RequestCopyOfOutput(request.Pass()); +} + void DelegatedFrameHost::UnlockResources() { DCHECK(frame_provider_.get() || !surface_id_.is_null()); delegated_frame_evictor_->UnlockFrame();
diff --git a/content/browser/compositor/delegated_frame_host.h b/content/browser/compositor/delegated_frame_host.h index 5943101..42ad05d 100644 --- a/content/browser/compositor/delegated_frame_host.h +++ b/content/browser/compositor/delegated_frame_host.h
@@ -25,6 +25,7 @@ namespace cc { class SurfaceFactory; +enum class SurfaceDrawStatus; } namespace media { @@ -44,26 +45,26 @@ // display them. class CONTENT_EXPORT DelegatedFrameHostClient { public: - virtual ui::Compositor* GetCompositor() const = 0; - virtual ui::Layer* GetLayer() = 0; - virtual RenderWidgetHostImpl* GetHost() = 0; - virtual bool IsVisible() = 0; - virtual scoped_ptr<ResizeLock> CreateResizeLock( + virtual ui::Layer* DelegatedFrameHostGetLayer() const = 0; + virtual bool DelegatedFrameHostIsVisible() const = 0; + virtual gfx::Size DelegatedFrameHostDesiredSizeInDIP() const = 0; + + virtual bool DelegatedFrameCanCreateResizeLock() const = 0; + virtual scoped_ptr<ResizeLock> DelegatedFrameHostCreateResizeLock( bool defer_compositor_lock) = 0; - virtual gfx::Size DesiredFrameSize() = 0; + virtual void DelegatedFrameHostResizeLockWasReleased() = 0; - // TODO(ccameron): It is likely that at least one of these two functions is - // redundant. Find which one, and delete it. - virtual float CurrentDeviceScaleFactor() = 0; - virtual gfx::Size ConvertViewSizeToPixel(const gfx::Size& size) = 0; + virtual void DelegatedFrameHostSendCompositorSwapAck( + int output_surface_id, + const cc::CompositorFrameAck& ack) = 0; + virtual void DelegatedFrameHostSendReclaimCompositorResources( + int output_surface_id, + const cc::CompositorFrameAck& ack) = 0; + virtual void DelegatedFrameHostOnLostCompositorResources() = 0; - // These are to be overridden for testing only. - // TODO(ccameron): This is convoluted. Make the tests that need to override - // these functions test DelegatedFrameHost directly (rather than do it - // through RenderWidgetHostViewAura). - virtual DelegatedFrameHost* GetDelegatedFrameHost() const = 0; - virtual bool ShouldCreateResizeLock(); - virtual void RequestCopyOfOutput(scoped_ptr<cc::CopyOutputRequest> request); + virtual void DelegatedFrameHostUpdateVSyncParameters( + const base::TimeTicks& timebase, + const base::TimeDelta& interval) = 0; }; // The DelegatedFrameHost is used to host all of the RenderWidgetHostView state @@ -96,8 +97,8 @@ void WasResized(); bool HasSavedFrame(); gfx::Size GetRequestedRendererSize() const; - void AddedToWindow(); - void RemovingFromWindow(); + void SetCompositor(ui::Compositor* compositor); + void ResetCompositor(); void CopyFromCompositingSurface(const gfx::Rect& src_subrect, const gfx::Size& output_size, ReadbackRequestCallback& callback, @@ -121,10 +122,13 @@ void OnCompositingDidCommitForTesting(ui::Compositor* compositor) { OnCompositingDidCommit(compositor); } - bool ShouldCreateResizeLockForTesting() { return ShouldCreateResizeLock(); } bool ReleasedFrontLockActiveForTesting() const { return !!released_front_lock_.get(); } + void SetRequestCopyOfOutputCallbackForTesting( + const base::Callback<void(scoped_ptr<cc::CopyOutputRequest>)>& callback) { + request_copy_of_output_callback_for_testing_ = callback; + } private: friend class DelegatedFrameHostClient; @@ -139,10 +143,9 @@ return frame_subscriber_.get(); } bool ShouldCreateResizeLock(); - void RequestCopyOfOutput(scoped_ptr<cc::CopyOutputRequest> request); - void LockResources(); void UnlockResources(); + void RequestCopyOfOutput(scoped_ptr<cc::CopyOutputRequest> request); // Overridden from ui::CompositorObserver: void OnCompositingDidCommit(ui::Compositor* compositor) override; @@ -151,6 +154,7 @@ void OnCompositingEnded(ui::Compositor* compositor) override; void OnCompositingAborted(ui::Compositor* compositor) override; void OnCompositingLockStateChanged(ui::Compositor* compositor) override; + void OnCompositingShuttingDown(ui::Compositor* compositor) override; // Overridden from ui::CompositorVSyncManager::Observer: void OnUpdateVSyncParameters(base::TimeTicks timebase, @@ -212,7 +216,7 @@ uint32 sync_point); void SendDelegatedFrameAck(uint32 output_surface_id); - void SurfaceDrawn(uint32 output_surface_id, bool drawn); + void SurfaceDrawn(uint32 output_surface_id, cc::SurfaceDrawStatus drawn); void SendReturnedDelegatedResources(uint32 output_surface_id); // DelegatedFrameEvictorClient implementation. @@ -226,7 +230,8 @@ void DidReceiveFrameFromRenderer(const gfx::Rect& damage_rect); - DelegatedFrameHostClient* client_; + DelegatedFrameHostClient* const client_; + ui::Compositor* compositor_; // True if this renders into a Surface, false if it renders into a delegated // layer. @@ -303,6 +308,11 @@ scoped_ptr<RenderWidgetHostViewFrameSubscriber> frame_subscriber_; std::vector<scoped_refptr<OwnedMailbox> > idle_frame_subscriber_textures_; + // Callback used to pass the output request to the layer or to a function + // specified by a test. + base::Callback<void(scoped_ptr<cc::CopyOutputRequest>)> + request_copy_of_output_callback_for_testing_; + // YUV readback pipeline. scoped_ptr<content::ReadbackYUVInterface> yuv_readback_pipeline_;
diff --git a/content/browser/compositor/onscreen_display_client.h b/content/browser/compositor/onscreen_display_client.h index 522274a..be218879 100644 --- a/content/browser/compositor/onscreen_display_client.h +++ b/content/browser/compositor/onscreen_display_client.h
@@ -46,6 +46,8 @@ void OutputSurfaceLost() override; void SetMemoryPolicy(const cc::ManagedMemoryPolicy& policy) override; + bool output_surface_lost() { return output_surface_lost_; } + private: void ScheduleDraw(); void Draw();
diff --git a/content/browser/compositor/reflector_impl.cc b/content/browser/compositor/reflector_impl.cc index ac3bdda7..c2d19b13 100644 --- a/content/browser/compositor/reflector_impl.cc +++ b/content/browser/compositor/reflector_impl.cc
@@ -38,7 +38,9 @@ ui::Layer* mirroring_layer) : needs_set_mailbox(true), mirrored_compositor(mirrored_compositor), - mirroring_layer(mirroring_layer) {} + mirroring_layer(mirroring_layer), + flip_texture(false) { +} ReflectorImpl::MainThreadData::~MainThreadData() {} @@ -193,10 +195,10 @@ impl.gl_helper->Flush(); output_surface->SetReflector(this); // The texture doesn't have the data, so invokes full redraw now. + bool flip_texture = !output_surface->capabilities().flipped_output_surface; main_message_loop_->PostTask( - FROM_HERE, - base::Bind(&ReflectorImpl::FullRedrawContentOnMainThread, - scoped_refptr<ReflectorImpl>(this))); + FROM_HERE, base::Bind(&ReflectorImpl::FullRedrawContentOnMainThread, + scoped_refptr<ReflectorImpl>(this), flip_texture)); } void ReflectorImpl::UpdateTextureSizeOnMainThread(gfx::Size size) { @@ -215,6 +217,7 @@ main.mirroring_layer->SetTextureSize(size); } main.mirroring_layer->SetBounds(gfx::Rect(size)); + main.mirroring_layer->SetTextureFlipped(main.flip_texture); } void ReflectorImpl::FullRedrawOnMainThread(gfx::Size size) { @@ -225,20 +228,24 @@ main.mirroring_layer->SchedulePaint(main.mirroring_layer->bounds()); } -void ReflectorImpl::UpdateSubBufferOnMainThread(gfx::Size size, - gfx::Rect rect) { +void ReflectorImpl::UpdateSubBufferOnMainThread(const gfx::Size& size, + const gfx::Rect& rect) { MainThreadData& main = GetMain(); if (!main.mirroring_layer) return; UpdateTextureSizeOnMainThread(size); + + int y = rect.y(); // Flip the coordinates to compositor's one. - int y = size.height() - rect.y() - rect.height(); + if (main.flip_texture) + y = size.height() - rect.y() - rect.height(); gfx::Rect new_rect(rect.x(), y, rect.width(), rect.height()); main.mirroring_layer->SchedulePaint(new_rect); } -void ReflectorImpl::FullRedrawContentOnMainThread() { +void ReflectorImpl::FullRedrawContentOnMainThread(bool flip_texture) { MainThreadData& main = GetMain(); + main.flip_texture = flip_texture; main.mirrored_compositor->ScheduleFullRedraw(); }
diff --git a/content/browser/compositor/reflector_impl.h b/content/browser/compositor/reflector_impl.h index 4d0da018..2e3b1b8 100644 --- a/content/browser/compositor/reflector_impl.h +++ b/content/browser/compositor/reflector_impl.h
@@ -10,6 +10,7 @@ #include "base/memory/weak_ptr.h" #include "base/synchronization/lock.h" #include "content/browser/compositor/image_transport_factory.h" +#include "content/common/content_export.h" #include "gpu/command_buffer/common/mailbox_holder.h" #include "ui/compositor/reflector.h" #include "ui/gfx/geometry/size.h" @@ -30,8 +31,9 @@ // A reflector implementation that copies the framebuffer content // to the texture, then draw it onto the mirroring compositor. -class ReflectorImpl : public base::SupportsWeakPtr<ReflectorImpl>, - public ui::Reflector { +class CONTENT_EXPORT ReflectorImpl + : public base::SupportsWeakPtr<ReflectorImpl>, + public ui::Reflector { public: ReflectorImpl( ui::Compositor* mirrored_compositor, @@ -78,6 +80,8 @@ void DetachFromOutputSurface(); private: + friend class ReflectorImplTest; + struct MainThreadData { MainThreadData(ui::Compositor* mirrored_compositor, ui::Layer* mirroring_layer); @@ -86,6 +90,7 @@ bool needs_set_mailbox; ui::Compositor* mirrored_compositor; ui::Layer* mirroring_layer; + bool flip_texture; }; struct ImplThreadData { @@ -110,11 +115,12 @@ // Request full redraw on mirroring compositor. void FullRedrawOnMainThread(gfx::Size size); - void UpdateSubBufferOnMainThread(gfx::Size size, gfx::Rect rect); + void UpdateSubBufferOnMainThread(const gfx::Size& size, + const gfx::Rect& rect); // Request full redraw on mirrored compositor so that // the full content will be copied to mirroring compositor. - void FullRedrawContentOnMainThread(); + void FullRedrawContentOnMainThread(bool flip_texture); // This exists just to hold a reference to a ReflectorImpl in a post task, // so the ReflectorImpl gets deleted when the function returns.
diff --git a/content/browser/compositor/reflector_impl_unittest.cc b/content/browser/compositor/reflector_impl_unittest.cc new file mode 100644 index 0000000..7483ae6 --- /dev/null +++ b/content/browser/compositor/reflector_impl_unittest.cc
@@ -0,0 +1,155 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/message_loop/message_loop.h" +#include "base/run_loop.h" +#include "base/single_thread_task_runner.h" +#include "cc/test/fake_output_surface_client.h" +#include "cc/test/test_context_provider.h" +#include "cc/test/test_web_graphics_context_3d.h" +#include "content/browser/compositor/browser_compositor_output_surface.h" +#include "content/browser/compositor/reflector_impl.h" +#include "content/browser/compositor/test/no_transport_image_transport_factory.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/compositor/compositor.h" +#include "ui/compositor/layer.h" +#include "ui/compositor/test/context_factories_for_test.h" + +namespace content { +namespace { +class FakeTaskRunner : public base::SingleThreadTaskRunner { + public: + FakeTaskRunner() {} + + bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here, + const base::Closure& task, + base::TimeDelta delay) override { + return true; + } + bool PostDelayedTask(const tracked_objects::Location& from_here, + const base::Closure& task, + base::TimeDelta delay) override { + return true; + } + bool RunsTasksOnCurrentThread() const override { return true; } + + protected: + ~FakeTaskRunner() override {} +}; + +class TestOutputSurface : public BrowserCompositorOutputSurface { + public: + TestOutputSurface( + const scoped_refptr<cc::ContextProvider>& context_provider, + int surface_id, + IDMap<BrowserCompositorOutputSurface>* output_surface_map, + const scoped_refptr<ui::CompositorVSyncManager>& vsync_manager) + : BrowserCompositorOutputSurface(context_provider, + surface_id, + output_surface_map, + vsync_manager) {} + + void SetFlip(bool flip) { capabilities_.flipped_output_surface = flip; } + + void SwapBuffers(cc::CompositorFrame* frame) override {} + +#if defined(OS_MACOSX) + void OnSurfaceDisplayed() override {} + void OnSurfaceRecycled() override {} + bool ShouldNotShowFramesAfterRecycle() const override { return false; } +#endif + + gfx::Size SurfaceSize() const override { return gfx::Size(256, 256); } +}; + +const gfx::Rect kSubRect = gfx::Rect(0, 0, 64, 64); +const SkIRect kSkSubRect = SkIRect::MakeXYWH(0, 0, 64, 64); + +} // namespace + +class ReflectorImplTest : public testing::Test { + public: + void SetUp() override { + bool enable_pixel_output = false; + ui::ContextFactory* context_factory = + ui::InitializeContextFactoryForTests(enable_pixel_output); + ImageTransportFactory::InitializeForUnitTests( + scoped_ptr<ImageTransportFactory>( + new NoTransportImageTransportFactory)); + message_loop_.reset(new base::MessageLoop()); + proxy_ = message_loop_->message_loop_proxy(); + compositor_task_runner_ = new FakeTaskRunner(); + compositor_.reset(new ui::Compositor(gfx::kNullAcceleratedWidget, + context_factory, + compositor_task_runner_.get())); + context_provider_ = cc::TestContextProvider::Create( + cc::TestWebGraphicsContext3D::Create().Pass()); + output_surface_ = + scoped_ptr<TestOutputSurface>( + new TestOutputSurface(context_provider_, 1, &surface_map_, + compositor_->vsync_manager())).Pass(); + CHECK(output_surface_->BindToClient(&output_surface_client_)); + + mirroring_layer_.reset(new ui::Layer()); + gfx::Size size = output_surface_->SurfaceSize(); + mirroring_layer_->SetBounds(gfx::Rect(size.width(), size.height())); + + int32 surface_id = 1; + reflector_ = new ReflectorImpl(compositor_.get(), mirroring_layer_.get(), + &surface_map_, proxy_.get(), surface_id); + } + + void TearDown() override { + cc::TextureMailbox mailbox; + scoped_ptr<cc::SingleReleaseCallback> release; + if (mirroring_layer_->PrepareTextureMailbox(&mailbox, &release, false)) { + release->Run(0, false); + } + compositor_.reset(); + ui::TerminateContextFactoryForTests(); + ImageTransportFactory::Terminate(); + } + + void Init() { base::RunLoop().RunUntilIdle(); } + + void UpdateTexture() { + reflector_->UpdateSubBufferOnMainThread(output_surface_->SurfaceSize(), + kSubRect); + } + + protected: + scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_; + IDMap<BrowserCompositorOutputSurface> surface_map_; + scoped_refptr<cc::ContextProvider> context_provider_; + cc::FakeOutputSurfaceClient output_surface_client_; + scoped_ptr<base::MessageLoop> message_loop_; + scoped_refptr<base::MessageLoopProxy> proxy_; + scoped_ptr<ui::Compositor> compositor_; + scoped_ptr<ui::Layer> mirroring_layer_; + scoped_refptr<ReflectorImpl> reflector_; + scoped_ptr<TestOutputSurface> output_surface_; +}; + +namespace { +TEST_F(ReflectorImplTest, CheckNormalOutputSurface) { + output_surface_->SetFlip(false); + Init(); + UpdateTexture(); + EXPECT_TRUE(mirroring_layer_->TextureFlipped()); + EXPECT_EQ(SkRegion(SkIRect::MakeXYWH( + 0, output_surface_->SurfaceSize().height() - kSubRect.height(), + kSubRect.width(), kSubRect.height())), + mirroring_layer_->damaged_region()); +} + +TEST_F(ReflectorImplTest, CheckInvertedOutputSurface) { + output_surface_->SetFlip(true); + Init(); + UpdateTexture(); + EXPECT_FALSE(mirroring_layer_->TextureFlipped()); + EXPECT_EQ(SkRegion(kSkSubRect), mirroring_layer_->damaged_region()); +} + +} // namespace +} // namespace content
diff --git a/content/browser/compositor/surface_display_output_surface.cc b/content/browser/compositor/surface_display_output_surface.cc index 61eee552..c4628ed 100644 --- a/content/browser/compositor/surface_display_output_surface.cc +++ b/content/browser/compositor/surface_display_output_surface.cc
@@ -93,8 +93,9 @@ client_->ReclaimResources(&ack); } -void SurfaceDisplayOutputSurface::SwapBuffersComplete(bool drawn) { - if (client_) +void SurfaceDisplayOutputSurface::SwapBuffersComplete( + cc::SurfaceDrawStatus drawn) { + if (client_ && !display_client_->output_surface_lost()) client_->DidSwapBuffersComplete(); }
diff --git a/content/browser/compositor/surface_display_output_surface.h b/content/browser/compositor/surface_display_output_surface.h index 8c16f4793..670aea7 100644 --- a/content/browser/compositor/surface_display_output_surface.h +++ b/content/browser/compositor/surface_display_output_surface.h
@@ -47,7 +47,7 @@ void ReturnResources(const cc::ReturnedResourceArray& resources) override; private: - void SwapBuffersComplete(bool drawn); + void SwapBuffersComplete(cc::SurfaceDrawStatus drawn); OnscreenDisplayClient* display_client_; cc::SurfaceManager* surface_manager_;
diff --git a/content/browser/devtools/ipc_devtools_agent_host.cc b/content/browser/devtools/ipc_devtools_agent_host.cc index 9218d58..b6b52fe 100644 --- a/content/browser/devtools/ipc_devtools_agent_host.cc +++ b/content/browser/devtools/ipc_devtools_agent_host.cc
@@ -4,8 +4,6 @@ #include "content/browser/devtools/ipc_devtools_agent_host.h" -#include "content/common/devtools_messages.h" - namespace content { void IPCDevToolsAgentHost::Attach() { @@ -36,31 +34,35 @@ IPCDevToolsAgentHost::~IPCDevToolsAgentHost() { } -void IPCDevToolsAgentHost::Reattach(const std::string& saved_agent_state) { +void IPCDevToolsAgentHost::Reattach() { SendMessageToAgent(new DevToolsAgentMsg_Reattach( - MSG_ROUTING_NONE, GetId(), saved_agent_state)); + MSG_ROUTING_NONE, GetId(), state_cookie_)); OnClientAttached(); } void IPCDevToolsAgentHost::ProcessChunkedMessageFromAgent( - const std::string& message, uint32 total_size) { - if (total_size && total_size == message.length()) { - DCHECK(message_buffer_size_ == 0); - SendMessageToClient(message); + const DevToolsMessageChunk& chunk) { + if (chunk.is_last && !chunk.post_state.empty()) + state_cookie_ = chunk.post_state; + + if (chunk.is_first && chunk.is_last) { + CHECK(message_buffer_size_ == 0); + SendMessageToClient(chunk.data); return; } - if (total_size) { - DCHECK(message_buffer_size_ == 0); + if (chunk.is_first) { message_buffer_ = std::string(); - message_buffer_.reserve(total_size); - message_buffer_size_ = total_size; + message_buffer_.reserve(chunk.message_size); + message_buffer_size_ = chunk.message_size; } - message_buffer_.append(message); + CHECK(message_buffer_.size() + chunk.data.size() <= + message_buffer_size_); + message_buffer_.append(chunk.data); - if (message_buffer_.size() >= message_buffer_size_) { - DCHECK(message_buffer_.size() == message_buffer_size_); + if (chunk.is_last) { + CHECK(message_buffer_.size() == message_buffer_size_); SendMessageToClient(message_buffer_); message_buffer_ = std::string(); message_buffer_size_ = 0;
diff --git a/content/browser/devtools/ipc_devtools_agent_host.h b/content/browser/devtools/ipc_devtools_agent_host.h index a952588f..6478bc3 100644 --- a/content/browser/devtools/ipc_devtools_agent_host.h +++ b/content/browser/devtools/ipc_devtools_agent_host.h
@@ -6,6 +6,7 @@ #define CONTENT_BROWSER_DEVTOOLS_IPC_DEVTOOLS_AGENT_HOST_H_ #include "content/browser/devtools/devtools_agent_host_impl.h" +#include "content/common/devtools_messages.h" namespace IPC { class Message; @@ -25,9 +26,8 @@ IPCDevToolsAgentHost(); ~IPCDevToolsAgentHost() override; - void Reattach(const std::string& saved_agent_state); - void ProcessChunkedMessageFromAgent(const std::string& message, - uint32 total_size); + void Reattach(); + void ProcessChunkedMessageFromAgent(const DevToolsMessageChunk& chunk); virtual void SendMessageToAgent(IPC::Message* msg) = 0; virtual void OnClientAttached() = 0; @@ -36,6 +36,7 @@ private: std::string message_buffer_; uint32 message_buffer_size_; + std::string state_cookie_; }; } // namespace content
diff --git a/content/browser/devtools/render_view_devtools_agent_host.cc b/content/browser/devtools/render_view_devtools_agent_host.cc index e6a12ca..1f1edec 100644 --- a/content/browser/devtools/render_view_devtools_agent_host.cc +++ b/content/browser/devtools/render_view_devtools_agent_host.cc
@@ -23,7 +23,6 @@ #include "content/browser/renderer_host/render_view_host_impl.h" #include "content/browser/site_instance_impl.h" #include "content/browser/web_contents/web_contents_impl.h" -#include "content/common/devtools_messages.h" #include "content/common/view_messages.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/content_browser_client.h" @@ -45,6 +44,17 @@ namespace { base::LazyInstance<Instances>::Leaky g_instances = LAZY_INSTANCE_INITIALIZER; +static RenderViewDevToolsAgentHost* FindAgentHost(RenderFrameHost* host) { + if (g_instances == NULL) + return NULL; + for (Instances::iterator it = g_instances.Get().begin(); + it != g_instances.Get().end(); ++it) { + if ((*it)->HasRenderFrameHost(host)) + return *it; + } + return NULL; +} + // Returns RenderViewDevToolsAgentHost attached to any of RenderFrameHost // instances associated with |web_contents| static RenderViewDevToolsAgentHost* FindAgentHost(WebContents* web_contents) { @@ -105,11 +115,7 @@ void RenderViewDevToolsAgentHost::OnCancelPendingNavigation( RenderFrameHost* pending, RenderFrameHost* current) { - if (current->GetParent()) - return; - WebContents* web_contents = - WebContents::FromRenderFrameHost(pending); - RenderViewDevToolsAgentHost* agent_host = FindAgentHost(web_contents); + RenderViewDevToolsAgentHost* agent_host = FindAgentHost(pending); if (!agent_host) return; agent_host->DisconnectRenderFrameHost(); @@ -268,30 +274,27 @@ // TODO(creis): Consider removing this in favor of RenderFrameHostChanged. void RenderViewDevToolsAgentHost::AboutToNavigateRenderFrame( - RenderFrameHost* render_frame_host) { - if (!render_frame_host_) - return; - if (render_frame_host->GetParent()) + RenderFrameHost* old_host, + RenderFrameHost* new_host) { + if (render_frame_host_ != old_host) return; // TODO(creis): This will need to be updated for --site-per-process, since // RenderViewHost is going away and navigations could happen in any frame. - if (render_frame_host_ == render_frame_host) { + if (render_frame_host_ == new_host) { RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>( render_frame_host_->GetRenderViewHost()); if (rvh->render_view_termination_status() == base::TERMINATION_STATUS_STILL_RUNNING) return; } - ReattachToRenderFrameHost(render_frame_host); + ReattachToRenderFrameHost(new_host); } void RenderViewDevToolsAgentHost::RenderFrameHostChanged( RenderFrameHost* old_host, RenderFrameHost* new_host) { - if (new_host->GetParent()) - return; - if (new_host != render_frame_host_) { + if (old_host == render_frame_host_ && new_host != render_frame_host_) { // AboutToNavigateRenderFrame was not called for renderer-initiated // navigation. ReattachToRenderFrameHost(new_host); @@ -354,8 +357,6 @@ IPC_BEGIN_MESSAGE_MAP(RenderViewDevToolsAgentHost, message) IPC_MESSAGE_HANDLER(DevToolsClientMsg_DispatchOnInspectorFrontend, OnDispatchOnInspectorFrontend) - IPC_MESSAGE_HANDLER(DevToolsHostMsg_SaveAgentRuntimeState, - OnSaveAgentRuntimeState) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; @@ -401,7 +402,6 @@ void RenderViewDevToolsAgentHost::SetRenderFrameHost(RenderFrameHost* rfh) { DCHECK(!render_frame_host_); - DCHECK(!rfh->GetParent()); render_frame_host_ = static_cast<RenderFrameHostImpl*>(rfh); WebContentsObserver::Observe(WebContents::FromRenderFrameHost(rfh)); @@ -477,7 +477,7 @@ void RenderViewDevToolsAgentHost::ConnectRenderFrameHost(RenderFrameHost* rfh) { SetRenderFrameHost(rfh); if (IsAttached()) - Reattach(state_); + Reattach(); } void RenderViewDevToolsAgentHost::DisconnectRenderFrameHost() { @@ -504,19 +504,16 @@ page_handler_->OnSwapCompositorFrame(frame_metadata); } -void RenderViewDevToolsAgentHost::OnSaveAgentRuntimeState( - const std::string& state) { - if (!render_frame_host_) - return; - state_ = state; +bool RenderViewDevToolsAgentHost::HasRenderFrameHost( + RenderFrameHost* host) { + return host == render_frame_host_; } void RenderViewDevToolsAgentHost::OnDispatchOnInspectorFrontend( - const std::string& message, - uint32 total_size) { + const DevToolsMessageChunk& message) { if (!IsAttached() || !render_frame_host_) return; - ProcessChunkedMessageFromAgent(message, total_size); + ProcessChunkedMessageFromAgent(message); } void RenderViewDevToolsAgentHost::DispatchOnInspectorFrontend(
diff --git a/content/browser/devtools/render_view_devtools_agent_host.h b/content/browser/devtools/render_view_devtools_agent_host.h index 9b8b605..dd509dcf 100644 --- a/content/browser/devtools/render_view_devtools_agent_host.h +++ b/content/browser/devtools/render_view_devtools_agent_host.h
@@ -52,6 +52,8 @@ void SynchronousSwapCompositorFrame( const cc::CompositorFrameMetadata& frame_metadata); + bool HasRenderFrameHost(RenderFrameHost* host); + // DevTooolsAgentHost overrides. void DisconnectWebContents() override; void ConnectWebContents(WebContents* web_contents) override; @@ -75,7 +77,8 @@ void OnClientDetached() override; // WebContentsObserver overrides. - void AboutToNavigateRenderFrame(RenderFrameHost* render_frame_host) override; + void AboutToNavigateRenderFrame(RenderFrameHost* old_host, + RenderFrameHost* new_host) override; void RenderFrameHostChanged(RenderFrameHost* old_host, RenderFrameHost* new_host) override; void RenderFrameDeleted(RenderFrameHost* rvh) override; @@ -105,10 +108,8 @@ void OnSwapCompositorFrame(const IPC::Message& message); bool OnSetTouchEventEmulationEnabled(const IPC::Message& message); - void OnDispatchOnInspectorFrontend(const std::string& message, - uint32 total_size); + void OnDispatchOnInspectorFrontend(const DevToolsMessageChunk& message); void DispatchOnInspectorFrontend(const std::string& message); - void OnSaveAgentRuntimeState(const std::string& state); void ClientDetachedFromRenderer(); @@ -127,7 +128,6 @@ #if defined(OS_ANDROID) scoped_ptr<PowerSaveBlockerImpl> power_save_blocker_; #endif - std::string state_; NotificationRegistrar registrar_; bool reattaching_;
diff --git a/content/browser/devtools/service_worker_devtools_manager.cc b/content/browser/devtools/service_worker_devtools_manager.cc index 18b3eb56f..eb744af 100644 --- a/content/browser/devtools/service_worker_devtools_manager.cc +++ b/content/browser/devtools/service_worker_devtools_manager.cc
@@ -9,7 +9,6 @@ #include "content/browser/devtools/service_worker_devtools_agent_host.h" #include "content/browser/devtools/shared_worker_devtools_agent_host.h" #include "content/browser/shared_worker/shared_worker_instance.h" -#include "content/common/devtools_messages.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/worker_service.h"
diff --git a/content/browser/devtools/worker_devtools_agent_host.cc b/content/browser/devtools/worker_devtools_agent_host.cc index ceb9a79..a95a50e 100644 --- a/content/browser/devtools/worker_devtools_agent_host.cc +++ b/content/browser/devtools/worker_devtools_agent_host.cc
@@ -4,8 +4,8 @@ #include "content/browser/devtools/worker_devtools_agent_host.h" +#include "content/browser/devtools/ipc_devtools_agent_host.h" #include "content/browser/devtools/protocol/devtools_protocol_handler.h" -#include "content/common/devtools_messages.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/render_process_host.h" @@ -60,8 +60,6 @@ IPC_BEGIN_MESSAGE_MAP(WorkerDevToolsAgentHost, msg) IPC_MESSAGE_HANDLER(DevToolsClientMsg_DispatchOnInspectorFrontend, OnDispatchOnInspectorFrontend) - IPC_MESSAGE_HANDLER(DevToolsHostMsg_SaveAgentRuntimeState, - OnSaveAgentRuntimeState) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; @@ -75,7 +73,7 @@ DCHECK(IsAttached()); state_ = WORKER_INSPECTED; AttachToWorker(); - Reattach(saved_agent_state_); + Reattach(); } } @@ -133,17 +131,11 @@ } void WorkerDevToolsAgentHost::OnDispatchOnInspectorFrontend( - const std::string& message, - uint32 total_size) { + const DevToolsMessageChunk& message) { if (!IsAttached()) return; - ProcessChunkedMessageFromAgent(message, total_size); -} - -void WorkerDevToolsAgentHost::OnSaveAgentRuntimeState( - const std::string& state) { - saved_agent_state_ = state; + ProcessChunkedMessageFromAgent(message); } } // namespace content
diff --git a/content/browser/devtools/worker_devtools_agent_host.h b/content/browser/devtools/worker_devtools_agent_host.h index 9a55c24..34750ed 100644 --- a/content/browser/devtools/worker_devtools_agent_host.h +++ b/content/browser/devtools/worker_devtools_agent_host.h
@@ -52,9 +52,7 @@ void AttachToWorker(); void DetachFromWorker(); void WorkerCreated(); - void OnDispatchOnInspectorFrontend(const std::string& message, - uint32 total_size); - void OnSaveAgentRuntimeState(const std::string& state); + void OnDispatchOnInspectorFrontend(const DevToolsMessageChunk& message); void set_state(WorkerState state) { state_ = state; } const WorkerId& worker_id() const { return worker_id_; } @@ -64,7 +62,6 @@ WorkerState state_; WorkerId worker_id_; - std::string saved_agent_state_; DISALLOW_COPY_AND_ASSIGN(WorkerDevToolsAgentHost); };
diff --git a/content/browser/fileapi/blob_storage_context_unittest.cc b/content/browser/fileapi/blob_storage_context_unittest.cc index 6ac1832..dccc869 100644 --- a/content/browser/fileapi/blob_storage_context_unittest.cc +++ b/content/browser/fileapi/blob_storage_context_unittest.cc
@@ -9,18 +9,24 @@ #include "base/run_loop.h" #include "base/time/time.h" #include "content/browser/fileapi/blob_storage_host.h" +#include "storage/browser/blob/blob_data_builder.h" #include "storage/browser/blob/blob_data_handle.h" +#include "storage/browser/blob/blob_data_snapshot.h" #include "storage/browser/blob/blob_storage_context.h" #include "testing/gtest/include/gtest/gtest.h" +using storage::BlobDataBuilder; using storage::BlobDataHandle; +using storage::BlobDataSnapshot; +using storage::BlobStorageContext; +using storage::DataElement; namespace content { namespace { void SetupBasicBlob(BlobStorageHost* host, const std::string& id) { EXPECT_TRUE(host->StartBuildingBlob(id)); - BlobData::Item item; + DataElement item; item.SetToBytes("1", 1); EXPECT_TRUE(host->AppendBlobDataItem(id, item)); EXPECT_TRUE(host->FinishBuildingBlob(id, "text/plain")); @@ -66,6 +72,22 @@ EXPECT_FALSE(host.IncrementBlobRefCount(kId)); } +TEST(BlobStorageContextTest, CancelBuildingBlob) { + BlobStorageContext context; + BlobStorageHost host(&context); + base::MessageLoop fake_io_message_loop; + + // Build up a basic blob. + const std::string kId("id"); + EXPECT_TRUE(host.StartBuildingBlob(kId)); + DataElement item; + item.SetToBytes("1", 1); + EXPECT_TRUE(host.AppendBlobDataItem(kId, item)); + EXPECT_TRUE(host.CancelBuildingBlob(kId)); + EXPECT_FALSE(host.FinishBuildingBlob(kId, "text/plain")); + EXPECT_TRUE(host.StartBuildingBlob(kId)); +} + TEST(BlobStorageContextTest, BlobDataHandle) { BlobStorageContext context; BlobStorageHost host(&context); @@ -111,19 +133,20 @@ base::Time::FromString("Tue, 15 Nov 1994, 12:45:26 GMT", &time1); base::Time::FromString("Mon, 14 Nov 1994, 11:30:49 GMT", &time2); - scoped_refptr<BlobData> blob_data1(new BlobData(kId1)); + scoped_ptr<BlobDataBuilder> blob_data1(new BlobDataBuilder(kId1)); blob_data1->AppendData("Data1"); blob_data1->AppendData("Data2"); blob_data1->AppendFile(base::FilePath(FILE_PATH_LITERAL("File1.txt")), 10, 1024, time1); - scoped_refptr<BlobData> blob_data2(new BlobData(kId2)); + scoped_ptr<BlobDataBuilder> blob_data2(new BlobDataBuilder(kId2)); blob_data2->AppendData("Data3"); blob_data2->AppendBlob(kId1, 8, 100); blob_data2->AppendFile(base::FilePath(FILE_PATH_LITERAL("File2.txt")), 0, 20, time2); - scoped_refptr<BlobData> canonicalized_blob_data2(new BlobData(kId2Prime)); + scoped_ptr<BlobDataBuilder> canonicalized_blob_data2( + new BlobDataBuilder(kId2Prime)); canonicalized_blob_data2->AppendData("Data3"); canonicalized_blob_data2->AppendData("a2___", 2); canonicalized_blob_data2->AppendFile( @@ -136,14 +159,18 @@ scoped_ptr<BlobDataHandle> blob_data_handle; // Test a blob referring to only data and a file. - blob_data_handle = context.AddFinishedBlob(blob_data1.get()); - ASSERT_TRUE(blob_data_handle.get()); - EXPECT_TRUE(*(blob_data_handle->data()) == *blob_data1.get()); + blob_data_handle = context.AddFinishedBlob(*blob_data1.get()); + ASSERT_TRUE(blob_data_handle); + scoped_ptr<BlobDataSnapshot> data = blob_data_handle->CreateSnapshot(); + ASSERT_TRUE(blob_data_handle); + EXPECT_EQ(*data, *blob_data1); // Test a blob composed in part with another blob. - blob_data_handle = context.AddFinishedBlob(blob_data2.get()); - ASSERT_TRUE(blob_data_handle.get()); - EXPECT_TRUE(*(blob_data_handle->data()) == *canonicalized_blob_data2.get()); + blob_data_handle = context.AddFinishedBlob(*blob_data2.get()); + data = blob_data_handle->CreateSnapshot(); + ASSERT_TRUE(blob_data_handle); + ASSERT_TRUE(data); + EXPECT_EQ(*data, *canonicalized_blob_data2); blob_data_handle.reset(); { // Clean up for ASAN @@ -167,7 +194,8 @@ scoped_ptr<BlobDataHandle> blob_data_handle = context.GetBlobDataFromPublicURL(kUrl); ASSERT_TRUE(blob_data_handle.get()); - EXPECT_EQ(kId, blob_data_handle->data()->uuid()); + EXPECT_EQ(kId, blob_data_handle->uuid()); + scoped_ptr<BlobDataSnapshot> data = blob_data_handle->CreateSnapshot(); blob_data_handle.reset(); { // Clean up for ASAN base::RunLoop run_loop; @@ -222,7 +250,7 @@ const std::string kId("id"); GURL kUrl("blob:id"); EXPECT_FALSE(host.StartBuildingBlob(kId)); - BlobData::Item item; + DataElement item; item.SetToBytes("1", 1); EXPECT_FALSE(host.AppendBlobDataItem(kId, item)); EXPECT_FALSE(host.FinishBuildingBlob(kId, "text/plain"));
diff --git a/content/browser/fileapi/blob_storage_host.cc b/content/browser/fileapi/blob_storage_host.cc index 87e675c..faf8101 100644 --- a/content/browser/fileapi/blob_storage_host.cc +++ b/content/browser/fileapi/blob_storage_host.cc
@@ -6,12 +6,10 @@ #include "base/sequenced_task_runner.h" #include "base/strings/string_util.h" -#include "storage/browser/blob/blob_data_handle.h" #include "storage/browser/blob/blob_storage_context.h" #include "url/gurl.h" using storage::BlobStorageContext; -using storage::BlobData; namespace content { @@ -42,7 +40,8 @@ } bool BlobStorageHost::AppendBlobDataItem( - const std::string& uuid, const BlobData::Item& data_item) { + const std::string& uuid, + const storage::DataElement& data_item) { if (!context_.get() || !IsBeingBuiltInHost(uuid)) return false; context_->AppendBlobDataItem(uuid, data_item);
diff --git a/content/browser/fileapi/blob_storage_host.h b/content/browser/fileapi/blob_storage_host.h index 3544f39..8fd8453f 100644 --- a/content/browser/fileapi/blob_storage_host.h +++ b/content/browser/fileapi/blob_storage_host.h
@@ -12,7 +12,7 @@ #include "base/compiler_specific.h" #include "base/memory/weak_ptr.h" #include "content/common/content_export.h" -#include "storage/common/blob/blob_data.h" +#include "storage/common/data_element.h" class GURL; @@ -22,9 +22,6 @@ class BlobStorageContext; } -using storage::BlobStorageContext; -using storage::BlobData; - namespace content { // This class handles the logistics of blob storage for a single child process. @@ -34,7 +31,7 @@ // only be used on the IO thread. class CONTENT_EXPORT BlobStorageHost { public: - explicit BlobStorageHost(BlobStorageContext* context); + explicit BlobStorageHost(storage::BlobStorageContext* context); ~BlobStorageHost(); // Methods to support the IPC message protocol. @@ -42,7 +39,8 @@ // like a non-existent or pre-existent uuid or url. bool StartBuildingBlob(const std::string& uuid) WARN_UNUSED_RESULT; bool AppendBlobDataItem(const std::string& uuid, - const BlobData::Item& data_item) WARN_UNUSED_RESULT; + const storage::DataElement& data_item) + WARN_UNUSED_RESULT; bool CancelBuildingBlob(const std::string& uuid) WARN_UNUSED_RESULT; bool FinishBuildingBlob(const std::string& uuid, const std::string& type) WARN_UNUSED_RESULT; @@ -66,7 +64,7 @@ // The set of public blob urls coined by this consumer. std::set<GURL> public_blob_urls_; - base::WeakPtr<BlobStorageContext> context_; + base::WeakPtr<storage::BlobStorageContext> context_; DISALLOW_COPY_AND_ASSIGN(BlobStorageHost); };
diff --git a/content/browser/fileapi/blob_url_request_job_unittest.cc b/content/browser/fileapi/blob_url_request_job_unittest.cc index 79824772..e7ce119 100644 --- a/content/browser/fileapi/blob_url_request_job_unittest.cc +++ b/content/browser/fileapi/blob_url_request_job_unittest.cc
@@ -22,14 +22,16 @@ #include "net/url_request/url_request.h" #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_job_factory_impl.h" +#include "storage/browser/blob/blob_data_builder.h" +#include "storage/browser/blob/blob_data_snapshot.h" #include "storage/browser/blob/blob_url_request_job.h" #include "storage/browser/fileapi/file_system_context.h" #include "storage/browser/fileapi/file_system_operation_context.h" #include "storage/browser/fileapi/file_system_url.h" -#include "storage/common/blob/blob_data.h" #include "testing/gtest/include/gtest/gtest.h" -using storage::BlobData; +using storage::BlobDataSnapshot; +using storage::BlobDataBuilder; using storage::BlobURLRequestJob; namespace content { @@ -64,9 +66,8 @@ net::URLRequestJob* MaybeCreateJob( net::URLRequest* request, net::NetworkDelegate* network_delegate) const override { - return new BlobURLRequestJob(request, - network_delegate, - test_->blob_data_.get(), + return new BlobURLRequestJob(request, network_delegate, + test_->blob_data_->BuildSnapshot().Pass(), test_->file_system_context_.get(), base::MessageLoopProxy::current().get()); } @@ -76,8 +77,7 @@ }; BlobURLRequestJobTest() - : blob_data_(new BlobData()), - expected_status_code_(0) {} + : blob_data_(new BlobDataBuilder("uuid")), expected_status_code_(0) {} void SetUp() override { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); @@ -219,10 +219,10 @@ // Otherwise, this will fail a CHECK. int64 GetTotalBlobLength() const { int64 total = 0; - const std::vector<BlobData::Item>& items = blob_data_->items(); - for (std::vector<BlobData::Item>::const_iterator it = items.begin(); - it != items.end(); ++it) { - int64 length = base::checked_cast<int64>(it->length()); + scoped_ptr<BlobDataSnapshot> data = blob_data_->BuildSnapshot(); + const auto& items = data->items(); + for (const auto& item : items) { + int64 length = base::checked_cast<int64>(item->length()); CHECK(length <= kint64max - total); total += length; } @@ -243,7 +243,8 @@ base::MessageLoopForIO message_loop_; scoped_refptr<storage::FileSystemContext> file_system_context_; - scoped_refptr<BlobData> blob_data_; + scoped_ptr<BlobDataBuilder> blob_data_; + scoped_ptr<BlobDataSnapshot> blob_data_snapshot_; net::URLRequestJobFactoryImpl url_request_job_factory_; net::URLRequestContext url_request_context_; MockURLRequestDelegate url_request_delegate_;
diff --git a/content/browser/fileapi/chrome_blob_storage_context.cc b/content/browser/fileapi/chrome_blob_storage_context.cc index f085242..5fc26e40f 100644 --- a/content/browser/fileapi/chrome_blob_storage_context.cc +++ b/content/browser/fileapi/chrome_blob_storage_context.cc
@@ -9,6 +9,7 @@ #include "content/public/browser/blob_handle.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" +#include "storage/browser/blob/blob_data_builder.h" #include "storage/browser/blob/blob_data_handle.h" #include "storage/browser/blob/blob_storage_context.h" @@ -24,8 +25,7 @@ class BlobHandleImpl : public BlobHandle { public: explicit BlobHandleImpl(scoped_ptr<storage::BlobDataHandle> handle) - : handle_(handle.Pass()) { - } + : handle_(handle.Pass()) {} ~BlobHandleImpl() override {} @@ -69,11 +69,12 @@ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); std::string uuid(base::GenerateGUID()); - scoped_refptr<storage::BlobData> blob_data = new storage::BlobData(uuid); - blob_data->AppendData(data, length); + scoped_ptr<storage::BlobDataBuilder> blob_data_builder( + new storage::BlobDataBuilder(uuid)); + blob_data_builder->AppendData(data, length); scoped_ptr<storage::BlobDataHandle> blob_data_handle = - context_->AddFinishedBlob(blob_data.get()); + context_->AddFinishedBlob(*blob_data_builder.get()); if (!blob_data_handle) return scoped_ptr<BlobHandle>();
diff --git a/content/browser/fileapi/copy_or_move_file_validator_unittest.cc b/content/browser/fileapi/copy_or_move_file_validator_unittest.cc index ea2ba89..f9b8d15 100644 --- a/content/browser/fileapi/copy_or_move_file_validator_unittest.cc +++ b/content/browser/fileapi/copy_or_move_file_validator_unittest.cc
@@ -11,13 +11,13 @@ #include "content/public/test/mock_special_storage_policy.h" #include "content/public/test/test_file_system_backend.h" #include "content/public/test/test_file_system_context.h" +#include "storage/browser/blob/shareable_file_reference.h" #include "storage/browser/fileapi/copy_or_move_file_validator.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" #include "storage/browser/fileapi/file_system_url.h" #include "storage/browser/fileapi/isolated_context.h" -#include "storage/common/blob/shareable_file_reference.h" #include "storage/common/fileapi/file_system_util.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/content/browser/fileapi/file_system_operation_impl_unittest.cc b/content/browser/fileapi/file_system_operation_impl_unittest.cc index 23a8c2d..6f84204a 100644 --- a/content/browser/fileapi/file_system_operation_impl_unittest.cc +++ b/content/browser/fileapi/file_system_operation_impl_unittest.cc
@@ -18,6 +18,7 @@ #include "content/browser/quota/mock_quota_manager_proxy.h" #include "content/public/test/async_file_test_helper.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" #include "storage/browser/fileapi/file_system_operation_context.h" @@ -25,7 +26,6 @@ #include "storage/browser/fileapi/sandbox_file_system_backend.h" #include "storage/browser/quota/quota_manager.h" #include "storage/browser/quota/quota_manager_proxy.h" -#include "storage/common/blob/shareable_file_reference.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/file_system_operation_impl_write_unittest.cc b/content/browser/fileapi/file_system_operation_impl_write_unittest.cc index 9d3c181f..ca324ae 100644 --- a/content/browser/fileapi/file_system_operation_impl_write_unittest.cc +++ b/content/browser/fileapi/file_system_operation_impl_write_unittest.cc
@@ -25,7 +25,6 @@ #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/common/blob/blob_data.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/fileapi_message_filter.cc b/content/browser/fileapi/fileapi_message_filter.cc index 17e3abe4..b4ef0ce 100644 --- a/content/browser/fileapi/fileapi_message_filter.cc +++ b/content/browser/fileapi/fileapi_message_filter.cc
@@ -27,13 +27,14 @@ #include "net/base/mime_util.h" #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_context_getter.h" +#include "storage/browser/blob/blob_data_builder.h" #include "storage/browser/blob/blob_storage_context.h" +#include "storage/browser/blob/shareable_file_reference.h" #include "storage/browser/fileapi/file_observers.h" #include "storage/browser/fileapi/file_permission_policy.h" #include "storage/browser/fileapi/file_system_context.h" #include "storage/browser/fileapi/isolated_context.h" -#include "storage/common/blob/blob_data.h" -#include "storage/common/blob/shareable_file_reference.h" +#include "storage/common/data_element.h" #include "storage/common/fileapi/directory_entry.h" #include "storage/common/fileapi/file_system_info.h" #include "storage/common/fileapi/file_system_types.h" @@ -44,7 +45,7 @@ using storage::FileSystemBackend; using storage::FileSystemOperation; using storage::FileSystemURL; -using storage::BlobData; +using storage::BlobDataBuilder; using storage::BlobStorageContext; namespace content { @@ -519,9 +520,10 @@ } void FileAPIMessageFilter::OnAppendBlobDataItemToBlob( - const std::string& uuid, const BlobData::Item& item) { + const std::string& uuid, + const storage::DataElement& item) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - if (item.type() == BlobData::Item::TYPE_FILE_FILESYSTEM) { + if (item.type() == storage::DataElement::TYPE_FILE_FILESYSTEM) { FileSystemURL filesystem_url(context_->CrackURL(item.filesystem_url())); if (!FileSystemURLIsValid(context_, filesystem_url) || !security_policy_->CanReadFileSystemFile(process_id_, filesystem_url)) { @@ -529,7 +531,7 @@ return; } } - if (item.type() == BlobData::Item::TYPE_FILE && + if (item.type() == storage::DataElement::TYPE_FILE && !security_policy_->CanReadFile(process_id_, item.path())) { ignore_result(blob_storage_host_->CancelBuildingBlob(uuid)); return; @@ -560,7 +562,7 @@ return; } - BlobData::Item item; + storage::DataElement item; item.SetToSharedBytes(static_cast<char*>(shared_memory.memory()), buffer_size); ignore_result(blob_storage_host_->AppendBlobDataItem(uuid, item)); @@ -613,7 +615,8 @@ } void FileAPIMessageFilter::OnAppendBlobDataItemToStream( - const GURL& url, const BlobData::Item& item) { + const GURL& url, + const storage::DataElement& item) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); scoped_refptr<Stream> stream(GetStreamForURL(url)); @@ -623,7 +626,7 @@ return; // Data for stream is delivered as TYPE_BYTES item. - if (item.type() != BlobData::Item::TYPE_BYTES) { + if (item.type() != storage::DataElement::TYPE_BYTES) { BadMessageReceived(); return; }
diff --git a/content/browser/fileapi/fileapi_message_filter.h b/content/browser/fileapi/fileapi_message_filter.h index 8ba998a0..805778b4 100644 --- a/content/browser/fileapi/fileapi_message_filter.h +++ b/content/browser/fileapi/fileapi_message_filter.h
@@ -20,7 +20,6 @@ #include "content/public/browser/browser_message_filter.h" #include "storage/browser/fileapi/file_system_context.h" #include "storage/browser/fileapi/file_system_operation_runner.h" -#include "storage/common/blob/blob_data.h" #include "storage/common/fileapi/file_system_types.h" #include "storage/common/quota/quota_types.h" @@ -49,6 +48,7 @@ namespace storage { class ShareableFileReference; +class DataElement; } namespace content { @@ -130,7 +130,7 @@ void OnStartBuildingBlob(const std::string& uuid); void OnAppendBlobDataItemToBlob(const std::string& uuid, - const storage::BlobData::Item& item); + const storage::DataElement& item); void OnAppendSharedMemoryToBlob(const std::string& uuid, base::SharedMemoryHandle handle, size_t buffer_size); @@ -151,7 +151,7 @@ // TODO(tyoshino): Set |content_type| to the stream. void OnStartBuildingStream(const GURL& url, const std::string& content_type); void OnAppendBlobDataItemToStream(const GURL& url, - const storage::BlobData::Item& item); + const storage::DataElement& item); void OnAppendSharedMemoryToStream( const GURL& url, base::SharedMemoryHandle handle, size_t buffer_size); void OnFlushStream(const GURL& url);
diff --git a/content/browser/fileapi/fileapi_message_filter_unittest.cc b/content/browser/fileapi/fileapi_message_filter_unittest.cc index 5aef43a..58f555e 100644 --- a/content/browser/fileapi/fileapi_message_filter_unittest.cc +++ b/content/browser/fileapi/fileapi_message_filter_unittest.cc
@@ -25,7 +25,7 @@ #include "net/base/io_buffer.h" #include "storage/browser/blob/blob_storage_context.h" #include "storage/browser/fileapi/file_system_context.h" -#include "storage/common/blob/blob_data.h" +#include "storage/common/data_element.h" #include "testing/gtest/include/gtest/gtest.h" namespace content { @@ -197,7 +197,7 @@ StreamHostMsg_StartBuilding start_message(kUrl, kFakeContentType); EXPECT_TRUE(filter_->OnMessageReceived(start_message)); - storage::BlobData::Item item; + storage::DataElement item; const std::string kFakeData = "foobarbaz"; item.SetToBytes(kFakeData.data(), kFakeData.size()); StreamHostMsg_AppendBlobDataItem append_message(kUrl, item);
diff --git a/content/browser/fileapi/transient_file_util_unittest.cc b/content/browser/fileapi/transient_file_util_unittest.cc index faf20ca..2ed8b74 100644 --- a/content/browser/fileapi/transient_file_util_unittest.cc +++ b/content/browser/fileapi/transient_file_util_unittest.cc
@@ -9,11 +9,11 @@ #include "base/memory/scoped_ptr.h" #include "base/run_loop.h" #include "content/public/test/test_file_system_context.h" +#include "storage/browser/blob/scoped_file.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/fileapi/transient_file_util.h" -#include "storage/common/blob/scoped_file.h" #include "testing/gtest/include/gtest/gtest.h" using storage::FileSystemURL;
diff --git a/content/browser/frame_host/frame_tree_browsertest.cc b/content/browser/frame_host/frame_tree_browsertest.cc index e0d790fd..5a0c453 100644 --- a/content/browser/frame_host/frame_tree_browsertest.cc +++ b/content/browser/frame_host/frame_tree_browsertest.cc
@@ -139,7 +139,13 @@ // Test that we can navigate away if the previous renderer doesn't clean up its // child frames. -IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, NavigateWithLeftoverFrames) { +// Flaky on Mac. http://crbug.com/452018 +#if defined(OS_MACOSX) +#define MAYBE_NavigateWithLeftoverFrames DISABLED_NavigateWithLeftoverFrames +#else +#define MAYBE_NavigateWithLeftoverFrames NavigateWithLeftoverFrames +#endif +IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, MAYBE_NavigateWithLeftoverFrames) { GURL base_url = embedded_test_server()->GetURL("A.com", "/site_isolation/"); NavigateToURL(shell(),
diff --git a/content/browser/frame_host/frame_tree_node.cc b/content/browser/frame_host/frame_tree_node.cc index d5f9279..6c75717 100644 --- a/content/browser/frame_host/frame_tree_node.cc +++ b/content/browser/frame_host/frame_tree_node.cc
@@ -98,4 +98,16 @@ old_children.clear(); // May notify observers. } +bool FrameTreeNode::IsDescendantOf(FrameTreeNode* other) const { + if (!other || !other->child_count()) + return false; + + for (FrameTreeNode* node = parent(); node; node = node->parent()) { + if (node == other) + return true; + } + + return false; +} + } // namespace content
diff --git a/content/browser/frame_host/frame_tree_node.h b/content/browser/frame_host/frame_tree_node.h index 63b7426..f992998 100644 --- a/content/browser/frame_host/frame_tree_node.h +++ b/content/browser/frame_host/frame_tree_node.h
@@ -112,6 +112,8 @@ return render_manager_.current_frame_host(); } + bool IsDescendantOf(FrameTreeNode* other) const; + private: void set_parent(FrameTreeNode* parent) { parent_ = parent; }
diff --git a/content/browser/frame_host/navigation_controller_impl.cc b/content/browser/frame_host/navigation_controller_impl.cc index f4f184b..316889255 100644 --- a/content/browser/frame_host/navigation_controller_impl.cc +++ b/content/browser/frame_host/navigation_controller_impl.cc
@@ -129,7 +129,9 @@ // for now. existing_url == GURL(url::kAboutBlankURL) || existing_url.GetOrigin() == new_url.GetOrigin() || - !prefs.web_security_enabled; + !prefs.web_security_enabled || + (prefs.allow_universal_access_from_file_urls && + existing_url.SchemeIs(url::kFileScheme)); if (!is_same_origin && renderer_says_in_page) rfh->GetProcess()->ReceivedBadMessage(); return is_same_origin && renderer_says_in_page; @@ -446,7 +448,7 @@ bool safe_to_show_pending = pending_entry_ && // Require a new navigation. - pending_entry_->GetPageID() == -1 && + pending_entry_index_ == -1 && // Require either browser-initiated or an unmodified new tab. (!pending_entry_->is_renderer_initiated() || IsUnmodifiedBlankTab()); @@ -455,7 +457,7 @@ // can script the new tab before it commits. if (!safe_to_show_pending && pending_entry_ && - pending_entry_->GetPageID() != -1 && + pending_entry_index_ != -1 && IsInitialNavigation() && !pending_entry_->is_renderer_initiated()) safe_to_show_pending = true; @@ -733,6 +735,14 @@ params.transferred_global_request_id); entry->SetFrameToNavigate(params.frame_name); +#if defined(OS_ANDROID) + if (params.intent_received_timestamp > 0) { + entry->set_intent_received_timestamp( + base::TimeTicks() + + base::TimeDelta::FromMilliseconds(params.intent_received_timestamp)); + } +#endif + switch (params.load_type) { case LOAD_TYPE_DEFAULT: break;
diff --git a/content/browser/frame_host/navigation_controller_impl_unittest.cc b/content/browser/frame_host/navigation_controller_impl_unittest.cc index dfdfde7..7820fca 100644 --- a/content/browser/frame_host/navigation_controller_impl_unittest.cc +++ b/content/browser/frame_host/navigation_controller_impl_unittest.cc
@@ -3196,15 +3196,41 @@ EXPECT_TRUE(controller.IsURLInPageNavigation(other_url, true, main_test_rfh())); - // Don't believe the renderer if it claims a cross-origin navigation is - // in-page. + // Test allow_universal_access_from_file_urls flag. const GURL different_origin_url("http://www.example.com"); MockRenderProcessHost* rph = static_cast<MockRenderProcessHost*>(main_test_rfh()->GetProcess()); + WebPreferences prefs = test_rvh()->GetWebkitPreferences(); + prefs.allow_universal_access_from_file_urls = true; + test_rvh()->UpdateWebkitPreferences(prefs); + prefs = test_rvh()->GetWebkitPreferences(); + EXPECT_TRUE(prefs.allow_universal_access_from_file_urls); + // Allow in page navigation if existing URL is file scheme. + const GURL file_url("file:///foo/index.html"); + main_test_rfh()->SendNavigate(0, file_url); EXPECT_EQ(0, rph->bad_msg_count()); + EXPECT_TRUE(controller.IsURLInPageNavigation(different_origin_url, true, + main_test_rfh())); + EXPECT_EQ(0, rph->bad_msg_count()); + // Don't honor allow_universal_access_from_file_urls if existing URL is + // not file scheme. + main_test_rfh()->SendNavigate(0, url); EXPECT_FALSE(controller.IsURLInPageNavigation(different_origin_url, true, main_test_rfh())); EXPECT_EQ(1, rph->bad_msg_count()); + + // Remove allow_universal_access_from_file_urls flag. + prefs.allow_universal_access_from_file_urls = false; + test_rvh()->UpdateWebkitPreferences(prefs); + prefs = test_rvh()->GetWebkitPreferences(); + EXPECT_FALSE(prefs.allow_universal_access_from_file_urls); + + // Don't believe the renderer if it claims a cross-origin navigation is + // in-page. + EXPECT_EQ(1, rph->bad_msg_count()); + EXPECT_FALSE(controller.IsURLInPageNavigation(different_origin_url, true, + main_test_rfh())); + EXPECT_EQ(2, rph->bad_msg_count()); } // Some pages can have subframes with the same base URL (minus the reference) as
diff --git a/content/browser/frame_host/navigation_entry_impl.cc b/content/browser/frame_host/navigation_entry_impl.cc index 8176847a..849871a 100644 --- a/content/browser/frame_host/navigation_entry_impl.cc +++ b/content/browser/frame_host/navigation_entry_impl.cc
@@ -338,6 +338,12 @@ set_should_clear_history_list(false); set_frame_tree_node_id(-1); set_source_site_instance(nullptr); + +#if defined(OS_ANDROID) + // Reset the time stamp so that the metrics are not reported if this entry is + // loaded again in the future. + set_intent_received_timestamp(base::TimeTicks()); +#endif } void NavigationEntryImpl::SetScreenshotPNGData(
diff --git a/content/browser/frame_host/navigation_entry_impl.h b/content/browser/frame_host/navigation_entry_impl.h index 8505f5b..f458bc0 100644 --- a/content/browser/frame_host/navigation_entry_impl.h +++ b/content/browser/frame_host/navigation_entry_impl.h
@@ -7,6 +7,7 @@ #include "base/basictypes.h" #include "base/memory/ref_counted.h" +#include "base/time/time.h" #include "content/browser/site_instance_impl.h" #include "content/public/browser/favicon_status.h" #include "content/public/browser/global_request_id.h" @@ -223,6 +224,17 @@ frame_tree_node_id_ = frame_tree_node_id; } +#if defined(OS_ANDROID) + base::TimeTicks intent_received_timestamp() const { + return intent_received_timestamp_; + } + + void set_intent_received_timestamp( + const base::TimeTicks intent_received_timestamp) { + intent_received_timestamp_ = intent_received_timestamp; + } +#endif + private: // WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING // Session/Tab restore save portions of this class so that it can be recreated @@ -341,6 +353,12 @@ // TODO(creis): Move this to FrameNavigationEntry. int64 frame_tree_node_id_; +#if defined(OS_ANDROID) + // The time at which Chrome received the Android Intent that triggered this + // URL load operation. Reset at commit and not persisted. + base::TimeTicks intent_received_timestamp_; +#endif + // Used to store extra data to support browser features. This member is not // persisted, unless specific data is taken out/put back in at save/restore // time (see TabNavigation for an example of this).
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc index fcf83661..34647b9 100644 --- a/content/browser/frame_host/navigation_request.cc +++ b/content/browser/frame_host/navigation_request.cc
@@ -22,11 +22,21 @@ const NavigationEntryImpl& entry, FrameMsg_Navigate_Type::Value navigation_type, base::TimeTicks navigation_start) { + FrameMsg_UILoadMetricsReportType::Value report_type = + FrameMsg_UILoadMetricsReportType::NO_REPORT; + base::TimeTicks ui_timestamp = base::TimeTicks(); +#if defined(OS_ANDROID) + if (!entry.intent_received_timestamp().is_null()) + report_type = FrameMsg_UILoadMetricsReportType::REPORT_INTENT; + ui_timestamp = entry.intent_received_timestamp(); +#endif + scoped_ptr<NavigationRequest> navigation_request(new NavigationRequest( frame_tree_node, CommonNavigationParams(entry.GetURL(), entry.GetReferrer(), entry.GetTransitionType(), navigation_type, - !entry.IsViewSourceMode()), + !entry.IsViewSourceMode(),ui_timestamp, + report_type), CommitNavigationParams(entry.GetPageState(), entry.GetIsOverridingUserAgent(), navigation_start),
diff --git a/content/browser/frame_host/navigator_delegate.h b/content/browser/frame_host/navigator_delegate.h index 1de561b..94b7b39 100644 --- a/content/browser/frame_host/navigator_delegate.h +++ b/content/browser/frame_host/navigator_delegate.h
@@ -82,7 +82,8 @@ // Notifies the Navigator embedder that it is beginning to navigate a frame. virtual void AboutToNavigateRenderFrame( - RenderFrameHostImpl* render_frame_host) {} + RenderFrameHostImpl* old_host, + RenderFrameHostImpl* new_host) {} // Notifies the Navigator embedder that a navigation to pending // NavigationEntry has started in the browser process.
diff --git a/content/browser/frame_host/navigator_impl.cc b/content/browser/frame_host/navigator_impl.cc index 0bd424a..ebd10e97 100644 --- a/content/browser/frame_host/navigator_impl.cc +++ b/content/browser/frame_host/navigator_impl.cc
@@ -142,10 +142,19 @@ NavigationController::ReloadType reload_type, base::TimeTicks navigation_start, FrameMsg_Navigate_Params* params) { + FrameMsg_UILoadMetricsReportType::Value report_type = + FrameMsg_UILoadMetricsReportType::NO_REPORT; + base::TimeTicks ui_timestamp = base::TimeTicks(); +#if defined(OS_ANDROID) + if (!entry.intent_received_timestamp().is_null()) + report_type = FrameMsg_UILoadMetricsReportType::REPORT_INTENT; + ui_timestamp = entry.intent_received_timestamp(); +#endif + params->common_params = CommonNavigationParams( entry.GetURL(), entry.GetReferrer(), entry.GetTransitionType(), GetNavigationType(controller->GetBrowserContext(), entry, reload_type), - !entry.IsViewSourceMode()); + !entry.IsViewSourceMode(), ui_timestamp, report_type); params->request_params = RequestNavigationParams( entry.GetHasPostData(), entry.extra_headers(), @@ -415,8 +424,10 @@ dest_render_frame_host, entry.GetURL()); // Notify observers that we will navigate in this RenderFrame. - if (delegate_) - delegate_->AboutToNavigateRenderFrame(dest_render_frame_host); + if (delegate_) { + delegate_->AboutToNavigateRenderFrame(render_frame_host, + dest_render_frame_host); + } // Create the navigation parameters. // TODO(vitalybuka): Move this before AboutToNavigateRenderFrame once
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc index c2149ef..054b039 100644 --- a/content/browser/frame_host/render_frame_host_impl.cc +++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -645,8 +645,15 @@ FrameMsg_UILoadMetricsReportType::Value report_type, base::TimeTicks ui_timestamp) { if (report_type == FrameMsg_UILoadMetricsReportType::REPORT_LINK) { - UMA_HISTOGRAM_TIMES("Navigation.UI_OnLoadComplete.Link", - base::TimeTicks::Now() - ui_timestamp); + UMA_HISTOGRAM_CUSTOM_TIMES("Navigation.UI_OnLoadComplete.Link", + base::TimeTicks::Now() - ui_timestamp, + base::TimeDelta::FromMilliseconds(10), + base::TimeDelta::FromMinutes(10), 100); + } else if (report_type == FrameMsg_UILoadMetricsReportType::REPORT_INTENT) { + UMA_HISTOGRAM_CUSTOM_TIMES("Navigation.UI_OnLoadComplete.Intent", + base::TimeTicks::Now() - ui_timestamp, + base::TimeDelta::FromMilliseconds(10), + base::TimeDelta::FromMinutes(10), 100); } // This message is only sent for top-level frames. TODO(avi): when frame tree // mirroring works correctly, add a check here to enforce it. @@ -719,8 +726,18 @@ if (validated_params.report_type == FrameMsg_UILoadMetricsReportType::REPORT_LINK) { - UMA_HISTOGRAM_TIMES("Navigation.UI_OnCommitProvisionalLoad.Link", - base::TimeTicks::Now() - validated_params.ui_timestamp); + UMA_HISTOGRAM_CUSTOM_TIMES( + "Navigation.UI_OnCommitProvisionalLoad.Link", + base::TimeTicks::Now() - validated_params.ui_timestamp, + base::TimeDelta::FromMilliseconds(10), base::TimeDelta::FromMinutes(10), + 100); + } else if (validated_params.report_type == + FrameMsg_UILoadMetricsReportType::REPORT_INTENT) { + UMA_HISTOGRAM_CUSTOM_TIMES( + "Navigation.UI_OnCommitProvisionalLoad.Intent", + base::TimeTicks::Now() - validated_params.ui_timestamp, + base::TimeDelta::FromMilliseconds(10), base::TimeDelta::FromMinutes(10), + 100); } RenderProcessHost* process = GetProcess(); @@ -1540,6 +1557,13 @@ service_registry_.reset(); } +bool RenderFrameHostImpl::IsFocused() { + return GetView()->HasFocus() && + frame_tree_->GetFocusedFrame() && + (frame_tree_->GetFocusedFrame() == frame_tree_node() || + frame_tree_->GetFocusedFrame()->IsDescendantOf(frame_tree_node())); +} + void RenderFrameHostImpl::UpdateCrossProcessIframeAccessibility( const std::map<int32, int>& node_to_frame_routing_id_map) { for (const auto& iter : node_to_frame_routing_id_map) {
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h index e964975..c9193a3 100644 --- a/content/browser/frame_host/render_frame_host_impl.h +++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -134,9 +134,9 @@ void ExecuteJavaScript(const base::string16& javascript, const JavaScriptResultCallback& callback) override; void ExecuteJavaScriptForTests(const base::string16& javascript) override; + void ActivateFindInPageResultForAccessibility(int request_id) override; RenderViewHost* GetRenderViewHost() override; ServiceRegistry* GetServiceRegistry() override; - void ActivateFindInPageResultForAccessibility(int request_id) override; // IPC::Sender bool Send(IPC::Message* msg) override; @@ -405,6 +405,11 @@ // this instance and its associated render frame. void InvalidateMojoConnection(); + // Returns whether the frame is focused. A frame is considered focused when it + // is the parent chain of the focused frame within the frame tree. In + // addition, its associated RenderWidgetHostView has to be focused. + bool IsFocused(); + protected: friend class RenderFrameHostFactory;
diff --git a/content/browser/frame_host/render_frame_host_impl_browsertest.cc b/content/browser/frame_host/render_frame_host_impl_browsertest.cc new file mode 100644 index 0000000..4eba7f0 --- /dev/null +++ b/content/browser/frame_host/render_frame_host_impl_browsertest.cc
@@ -0,0 +1,81 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/frame_host/render_frame_host_impl.h" +#include "content/public/browser/render_frame_host.h" +#include "content/public/browser/web_contents.h" +#include "content/public/test/content_browser_test.h" +#include "content/public/test/content_browser_test_utils.h" +#include "content/public/test/test_utils.h" +#include "content/shell/browser/shell.h" + +namespace content { + +namespace { + +RenderFrameHostImpl* ToRFHI(RenderFrameHost* render_frame_host) { + return static_cast<RenderFrameHostImpl*>(render_frame_host); +} + +} // anonymous namespace + +using RenderFrameHostImplBrowserTest = ContentBrowserTest; + +// Test that when creating a new window, the main frame is correctly focused. +IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest, IsFocused_AtLoad) { + EXPECT_TRUE( + NavigateToURL(shell(), GetTestUrl("render_frame_host", "focus.html"))); + + // The main frame should be focused. + WebContents* web_contents = shell()->web_contents(); + EXPECT_TRUE(ToRFHI(web_contents->GetMainFrame())->IsFocused()); +} + +// Test that if the content changes the focused frame, it is correctly exposed. +IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest, IsFocused_Change) { + EXPECT_TRUE( + NavigateToURL(shell(), GetTestUrl("render_frame_host", "focus.html"))); + + WebContents* web_contents = shell()->web_contents(); + + std::string frames[2] = { "frame1", "frame2" }; + for (const std::string& frame : frames) { + ExecuteScriptAndGetValue( + web_contents->GetMainFrame(), "focus" + frame + "()"); + + // The main frame is not the focused frame in the frame tree but the main + // frame is focused per RFHI rules because one of its descendant is focused. + EXPECT_NE(web_contents->GetMainFrame(), web_contents->GetFocusedFrame()); + EXPECT_TRUE(ToRFHI(web_contents->GetFocusedFrame())->IsFocused()); + EXPECT_TRUE(ToRFHI(web_contents->GetMainFrame())->IsFocused()); + EXPECT_EQ(frame, web_contents->GetFocusedFrame()->GetFrameName()); + } +} + +// Test that even if the frame is focused in the frame tree but its +// RenderWidgetHost is not focused, it is not considered as focused. +IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest, IsFocused_Widget) { + EXPECT_TRUE( + NavigateToURL(shell(), GetTestUrl("render_frame_host", "focus.html"))); + WebContents* web_contents = shell()->web_contents(); + + // A second window is created and navigated. It takes the focus. + Shell* new_shell = CreateBrowser(); + EXPECT_TRUE( + NavigateToURL(new_shell, GetTestUrl("render_frame_host", "focus.html"))); + EXPECT_TRUE(ToRFHI(new_shell->web_contents()->GetMainFrame())->IsFocused()); + + // The first opened window is no longer focused. The main frame is still the + // focused frame in the frame tree but as far as RFH is concerned, the frame + // is not focused. + EXPECT_EQ(web_contents->GetMainFrame(), web_contents->GetFocusedFrame()); + +#if defined(OS_MACOSX) + EXPECT_TRUE(ToRFHI(web_contents->GetMainFrame())->IsFocused()); +#else + EXPECT_FALSE(ToRFHI(web_contents->GetMainFrame())->IsFocused()); +#endif +} + +} // namespace content
diff --git a/content/browser/frame_host/render_frame_host_manager_browsertest.cc b/content/browser/frame_host/render_frame_host_manager_browsertest.cc index 6a42223..4de22b0 100644 --- a/content/browser/frame_host/render_frame_host_manager_browsertest.cc +++ b/content/browser/frame_host/render_frame_host_manager_browsertest.cc
@@ -1562,8 +1562,16 @@ }; // Test for http://crbug.com/262948. +// Flaky on Mac. http://crbug.com/452018 +#if defined(OS_MACOSX) +#define MAYBE_RestoreFileAccessForHistoryNavigation \ + DISABLED_RestoreFileAccessForHistoryNavigation +#else +#define MAYBE_RestoreFileAccessForHistoryNavigation \ + RestoreFileAccessForHistoryNavigation +#endif IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, - RestoreFileAccessForHistoryNavigation) { + MAYBE_RestoreFileAccessForHistoryNavigation) { StartServer(); base::FilePath file; EXPECT_TRUE(PathService::Get(base::DIR_TEMP, &file));
diff --git a/content/browser/geolocation/wifi_data_provider_chromeos.h b/content/browser/geolocation/wifi_data_provider_chromeos.h index db56ea7..0e8bc93f 100644 --- a/content/browser/geolocation/wifi_data_provider_chromeos.h +++ b/content/browser/geolocation/wifi_data_provider_chromeos.h
@@ -16,13 +16,13 @@ WifiDataProviderChromeOs(); // WifiDataProvider - virtual void StartDataProvider() override; - virtual void StopDataProvider() override; - virtual bool GetData(WifiData* data) override; + void StartDataProvider() override; + void StopDataProvider() override; + bool GetData(WifiData* data) override; private: friend class GeolocationChromeOsWifiDataProviderTest; - virtual ~WifiDataProviderChromeOs(); + ~WifiDataProviderChromeOs() override; // UI thread void DoWifiScanTaskOnUIThread(); // The polling task
diff --git a/content/browser/geolocation/wifi_data_provider_chromeos_unittest.cc b/content/browser/geolocation/wifi_data_provider_chromeos_unittest.cc index eb04421..38c1ea3 100644 --- a/content/browser/geolocation/wifi_data_provider_chromeos_unittest.cc +++ b/content/browser/geolocation/wifi_data_provider_chromeos_unittest.cc
@@ -19,7 +19,7 @@ GeolocationChromeOsWifiDataProviderTest() { } - virtual void SetUp() override { + void SetUp() override { chromeos::DBusThreadManager::Initialize(); chromeos::NetworkHandler::Initialize(); manager_client_ = @@ -29,7 +29,7 @@ message_loop_.RunUntilIdle(); } - virtual void TearDown() override { + void TearDown() override { provider_ = NULL; chromeos::NetworkHandler::Shutdown(); chromeos::DBusThreadManager::Shutdown();
diff --git a/content/browser/gpu/compositor_util.cc b/content/browser/gpu/compositor_util.cc index 444f43c..2e2483a 100644 --- a/content/browser/gpu/compositor_util.cc +++ b/content/browser/gpu/compositor_util.cc
@@ -196,12 +196,8 @@ bool IsImplSidePaintingEnabled() { const base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess(); - - if (command_line.HasSwitch(switches::kEnableImplSidePainting)) - return true; - else if (command_line.HasSwitch(switches::kDisableImplSidePainting)) + if (command_line.HasSwitch(switches::kDisableImplSidePainting)) return false; - return true; } @@ -233,7 +229,7 @@ if (command_line.HasSwitch(switches::kDisableOneCopy)) return false; -#if defined(OS_MACOSX) || defined(OS_ANDROID) +#if defined(OS_ANDROID) return false; #endif return true;
diff --git a/content/browser/gpu/gpu_data_manager_impl_private.cc b/content/browser/gpu/gpu_data_manager_impl_private.cc index b3b1627a..1b484ce 100644 --- a/content/browser/gpu/gpu_data_manager_impl_private.cc +++ b/content/browser/gpu/gpu_data_manager_impl_private.cc
@@ -495,8 +495,7 @@ return; } - const base::CommandLine* command_line = - base::CommandLine::ForCurrentProcess(); + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); if (command_line->HasSwitch(switches::kSkipGpuDataLoading)) return; @@ -540,6 +539,12 @@ InitializeImpl(gpu_blacklist_string, gpu_driver_bug_list_string, gpu_info); + + if (command_line->HasSwitch(switches::kSingleProcess) || + command_line->HasSwitch(switches::kInProcessGPU)) { + command_line->AppendSwitch(switches::kDisableGpuWatchdog); + AppendGpuCommandLine(command_line); + } } void GpuDataManagerImplPrivate::UpdateGpuInfoHelper() {
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc index 991dbda..a234562 100644 --- a/content/browser/gpu/gpu_process_host.cc +++ b/content/browser/gpu/gpu_process_host.cc
@@ -504,13 +504,6 @@ if (in_process_) { DCHECK(g_gpu_main_thread_factory); - base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - command_line->AppendSwitch(switches::kDisableGpuWatchdog); - - GpuDataManagerImpl* gpu_data_manager = GpuDataManagerImpl::GetInstance(); - DCHECK(gpu_data_manager); - gpu_data_manager->AppendGpuCommandLine(command_line); - in_process_gpu_thread_.reset(g_gpu_main_thread_factory(channel_id)); base::Thread::Options options; #if defined(OS_WIN)
diff --git a/content/browser/indexed_db/indexed_db_active_blob_registry.h b/content/browser/indexed_db/indexed_db_active_blob_registry.h index b0ebe27f..8f78f19 100644 --- a/content/browser/indexed_db/indexed_db_active_blob_registry.h +++ b/content/browser/indexed_db/indexed_db_active_blob_registry.h
@@ -12,7 +12,7 @@ #include "base/files/file_path.h" #include "base/memory/weak_ptr.h" #include "content/common/content_export.h" -#include "storage/common/blob/shareable_file_reference.h" +#include "storage/browser/blob/shareable_file_reference.h" namespace content {
diff --git a/content/browser/indexed_db/indexed_db_blob_info.h b/content/browser/indexed_db/indexed_db_blob_info.h index 5001b4b..02d039d 100644 --- a/content/browser/indexed_db/indexed_db_blob_info.h +++ b/content/browser/indexed_db/indexed_db_blob_info.h
@@ -11,7 +11,7 @@ #include "base/files/file_path.h" #include "base/time/time.h" #include "content/common/content_export.h" -#include "storage/common/blob/shareable_file_reference.h" +#include "storage/browser/blob/shareable_file_reference.h" namespace content {
diff --git a/content/browser/indexed_db/indexed_db_callbacks.cc b/content/browser/indexed_db/indexed_db_callbacks.cc index e38c8989..147c5ab 100644 --- a/content/browser/indexed_db/indexed_db_callbacks.cc +++ b/content/browser/indexed_db/indexed_db_callbacks.cc
@@ -22,9 +22,8 @@ #include "content/common/indexed_db/indexed_db_constants.h" #include "content/common/indexed_db/indexed_db_messages.h" #include "storage/browser/blob/blob_storage_context.h" +#include "storage/browser/blob/shareable_file_reference.h" #include "storage/browser/quota/quota_manager.h" -#include "storage/common/blob/blob_data.h" -#include "storage/common/blob/shareable_file_reference.h" using storage::ShareableFileReference;
diff --git a/content/browser/indexed_db/indexed_db_dispatcher_host.cc b/content/browser/indexed_db/indexed_db_dispatcher_host.cc index bbfe9eed..302adbcc 100644 --- a/content/browser/indexed_db/indexed_db_dispatcher_host.cc +++ b/content/browser/indexed_db/indexed_db_dispatcher_host.cc
@@ -27,6 +27,7 @@ #include "content/public/browser/user_metrics.h" #include "content/public/common/content_switches.h" #include "content/public/common/result_codes.h" +#include "storage/browser/blob/blob_data_builder.h" #include "storage/browser/blob/blob_storage_context.h" #include "storage/browser/database/database_util.h" #include "storage/common/database/database_identifier.h" @@ -226,11 +227,11 @@ scoped_ptr<storage::BlobDataHandle> blob_data_handle; if (uuid.empty()) { uuid = base::GenerateGUID(); - scoped_refptr<storage::BlobData> blob_data = new storage::BlobData(uuid); - blob_data->set_content_type(base::UTF16ToUTF8(blob_info.type())); - blob_data->AppendFile(blob_info.file_path(), 0, blob_info.size(), - blob_info.last_modified()); - blob_data_handle = context->AddFinishedBlob(blob_data.get()); + storage::BlobDataBuilder blob_data_builder(uuid); + blob_data_builder.set_content_type(base::UTF16ToUTF8(blob_info.type())); + blob_data_builder.AppendFile(blob_info.file_path(), 0, blob_info.size(), + blob_info.last_modified()); + blob_data_handle = context->AddFinishedBlob(blob_data_builder); } else { auto iter = blob_data_handle_map_.find(uuid); if (iter != blob_data_handle_map_.end()) { @@ -613,7 +614,10 @@ int32 ipc_object_id) { DCHECK( parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread()); - IndexedDBConnection* connection = map_.Lookup(ipc_object_id); + IndexedDBConnection* connection = + parent_->GetOrTerminateProcess(&map_, ipc_object_id); + if (!connection) + return; if (connection->IsConnected()) connection->Close(); parent_->Context()
diff --git a/content/browser/loader/redirect_to_file_resource_handler.cc b/content/browser/loader/redirect_to_file_resource_handler.cc index 00e6392..6f402135 100644 --- a/content/browser/loader/redirect_to_file_resource_handler.cc +++ b/content/browser/loader/redirect_to_file_resource_handler.cc
@@ -15,7 +15,7 @@ #include "net/base/io_buffer.h" #include "net/base/mime_sniffer.h" #include "net/base/net_errors.h" -#include "storage/common/blob/shareable_file_reference.h" +#include "storage/browser/blob/shareable_file_reference.h" using storage::ShareableFileReference;
diff --git a/content/browser/loader/resource_dispatcher_host_impl.cc b/content/browser/loader/resource_dispatcher_host_impl.cc index 31a53f7..332b7ec 100644 --- a/content/browser/loader/resource_dispatcher_host_impl.cc +++ b/content/browser/loader/resource_dispatcher_host_impl.cc
@@ -94,10 +94,9 @@ #include "storage/browser/blob/blob_data_handle.h" #include "storage/browser/blob/blob_storage_context.h" #include "storage/browser/blob/blob_url_request_job_factory.h" +#include "storage/browser/blob/shareable_file_reference.h" #include "storage/browser/fileapi/file_permission_policy.h" #include "storage/browser/fileapi/file_system_context.h" -#include "storage/common/blob/blob_data.h" -#include "storage/common/blob/shareable_file_reference.h" #include "url/url_constants.h" using base::Time;
diff --git a/content/browser/loader/resource_dispatcher_host_unittest.cc b/content/browser/loader/resource_dispatcher_host_unittest.cc index 999ad4a..332e726 100644 --- a/content/browser/loader/resource_dispatcher_host_unittest.cc +++ b/content/browser/loader/resource_dispatcher_host_unittest.cc
@@ -49,7 +49,7 @@ #include "net/url_request/url_request_simple_job.h" #include "net/url_request/url_request_test_job.h" #include "net/url_request/url_request_test_util.h" -#include "storage/common/blob/shareable_file_reference.h" +#include "storage/browser/blob/shareable_file_reference.h" #include "testing/gtest/include/gtest/gtest.h" // TODO(eroman): Write unit tests for SafeBrowsing that exercise
diff --git a/content/browser/loader/resource_loader_unittest.cc b/content/browser/loader/resource_loader_unittest.cc index 9123107..c9d3398 100644 --- a/content/browser/loader/resource_loader_unittest.cc +++ b/content/browser/loader/resource_loader_unittest.cc
@@ -27,7 +27,7 @@ #include "net/url_request/url_request_job_factory_impl.h" #include "net/url_request/url_request_test_job.h" #include "net/url_request/url_request_test_util.h" -#include "storage/common/blob/shareable_file_reference.h" +#include "storage/browser/blob/shareable_file_reference.h" #include "testing/gtest/include/gtest/gtest.h" using storage::ShareableFileReference;
diff --git a/content/browser/loader/temporary_file_stream.cc b/content/browser/loader/temporary_file_stream.cc index e904d88..eb3ea9e 100644 --- a/content/browser/loader/temporary_file_stream.cc +++ b/content/browser/loader/temporary_file_stream.cc
@@ -10,7 +10,7 @@ #include "base/memory/ref_counted.h" #include "content/public/browser/browser_thread.h" #include "net/base/file_stream.h" -#include "storage/common/blob/shareable_file_reference.h" +#include "storage/browser/blob/shareable_file_reference.h" using storage::ShareableFileReference;
diff --git a/content/browser/loader/temporary_file_stream_unittest.cc b/content/browser/loader/temporary_file_stream_unittest.cc index 854a5dd..af57f082 100644 --- a/content/browser/loader/temporary_file_stream_unittest.cc +++ b/content/browser/loader/temporary_file_stream_unittest.cc
@@ -18,7 +18,7 @@ #include "net/base/io_buffer.h" #include "net/base/net_errors.h" #include "net/base/test_completion_callback.h" -#include "storage/common/blob/shareable_file_reference.h" +#include "storage/browser/blob/shareable_file_reference.h" #include "testing/gtest/include/gtest/gtest.h" using storage::ShareableFileReference;
diff --git a/content/browser/loader/upload_data_stream_builder.cc b/content/browser/loader/upload_data_stream_builder.cc index 376e221d..c497c16 100644 --- a/content/browser/loader/upload_data_stream_builder.cc +++ b/content/browser/loader/upload_data_stream_builder.cc
@@ -11,12 +11,9 @@ #include "net/base/upload_bytes_element_reader.h" #include "net/base/upload_file_element_reader.h" #include "storage/browser/blob/blob_data_handle.h" +#include "storage/browser/blob/blob_data_snapshot.h" #include "storage/browser/blob/blob_storage_context.h" -using storage::BlobData; -using storage::BlobDataHandle; -using storage::BlobStorageContext; - namespace content { namespace { @@ -64,6 +61,7 @@ }; void ResolveBlobReference( + ResourceRequestBody* body, storage::BlobStorageContext* blob_context, const ResourceRequestBody::Element& element, std::vector<const ResourceRequestBody::Element*>* resolved_elements) { @@ -74,23 +72,29 @@ if (!handle) return; + // TODO(dmurph): Create a reader for blobs instead of decomposing the blob + // and storing the snapshot on the request to keep the resources around. + // Currently a handle is attached to the request in the resource dispatcher + // host, so we know the blob won't go away, but it's not very clear or useful. + scoped_ptr<storage::BlobDataSnapshot> snapshot = handle->CreateSnapshot(); // If there is no element in the referred blob data, just return. - if (handle->data()->items().empty()) + if (snapshot->items().empty()) return; // Append the elements in the referenced blob data. - for (size_t i = 0; i < handle->data()->items().size(); ++i) { - const BlobData::Item& item = handle->data()->items().at(i); - DCHECK_NE(BlobData::Item::TYPE_BLOB, item.type()); - resolved_elements->push_back(&item); + for (const auto& item : snapshot->items()) { + DCHECK_NE(storage::DataElement::TYPE_BLOB, item->type()); + resolved_elements->push_back(item->data_element_ptr()); } + const void* key = snapshot.get(); + body->SetUserData(key, snapshot.release()); } } // namespace scoped_ptr<net::UploadDataStream> UploadDataStreamBuilder::Build( ResourceRequestBody* body, - BlobStorageContext* blob_context, + storage::BlobStorageContext* blob_context, storage::FileSystemContext* file_system_context, base::TaskRunner* file_task_runner) { // Resolve all blob elements. @@ -98,7 +102,7 @@ for (size_t i = 0; i < body->elements()->size(); ++i) { const ResourceRequestBody::Element& element = (*body->elements())[i]; if (element.type() == ResourceRequestBody::Element::TYPE_BLOB) - ResolveBlobReference(blob_context, element, &resolved_elements); + ResolveBlobReference(body, blob_context, element, &resolved_elements); else resolved_elements.push_back(&element); } @@ -128,6 +132,7 @@ break; case ResourceRequestBody::Element::TYPE_BLOB: // Blob elements should be resolved beforehand. + // TODO(dmurph): Create blob reader and store the snapshot in there. NOTREACHED(); break; case ResourceRequestBody::Element::TYPE_UNKNOWN:
diff --git a/content/browser/loader/upload_data_stream_builder_unittest.cc b/content/browser/loader/upload_data_stream_builder_unittest.cc index dfd22b2..4f8e8d40 100644 --- a/content/browser/loader/upload_data_stream_builder_unittest.cc +++ b/content/browser/loader/upload_data_stream_builder_unittest.cc
@@ -16,11 +16,12 @@ #include "net/base/upload_bytes_element_reader.h" #include "net/base/upload_data_stream.h" #include "net/base/upload_file_element_reader.h" +#include "storage/browser/blob/blob_data_builder.h" #include "storage/browser/blob/blob_storage_context.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" -using storage::BlobData; +using storage::BlobDataBuilder; using storage::BlobDataHandle; using storage::BlobStorageContext; @@ -105,29 +106,30 @@ BlobStorageContext blob_storage_context; const std::string blob_id0("id-0"); - scoped_refptr<BlobData> blob_data(new BlobData(blob_id0)); + scoped_ptr<BlobDataBuilder> blob_data_builder( + new BlobDataBuilder(blob_id0)); scoped_ptr<BlobDataHandle> handle1 = - blob_storage_context.AddFinishedBlob(blob_data.get()); + blob_storage_context.AddFinishedBlob(*blob_data_builder.get()); const std::string blob_id1("id-1"); - blob_data = new BlobData(blob_id1); - blob_data->AppendData("BlobData"); - blob_data->AppendFile( + blob_data_builder.reset(new BlobDataBuilder(blob_id1)); + blob_data_builder->AppendData("BlobData"); + blob_data_builder->AppendFile( base::FilePath(FILE_PATH_LITERAL("BlobFile.txt")), 0, 20, time1); scoped_ptr<BlobDataHandle> handle2 = - blob_storage_context.AddFinishedBlob(blob_data.get()); + blob_storage_context.AddFinishedBlob(*blob_data_builder.get()); // Setup upload data elements for comparison. + auto blob_data = blob_data_builder->BuildSnapshot(); ResourceRequestBody::Element blob_element1, blob_element2; blob_element1.SetToBytes( - blob_data->items().at(0).bytes() + - static_cast<int>(blob_data->items().at(0).offset()), - static_cast<int>(blob_data->items().at(0).length())); + blob_data->items().at(0)->bytes() + + static_cast<int>(blob_data->items().at(0)->offset()), + static_cast<int>(blob_data->items().at(0)->length())); blob_element2.SetToFilePathRange( - blob_data->items().at(1).path(), - blob_data->items().at(1).offset(), - blob_data->items().at(1).length(), - blob_data->items().at(1).expected_modification_time()); + blob_data->items().at(1)->path(), blob_data->items().at(1)->offset(), + blob_data->items().at(1)->length(), + blob_data->items().at(1)->expected_modification_time()); ResourceRequestBody::Element upload_element1, upload_element2; upload_element1.SetToBytes("Hello", 5);
diff --git a/content/browser/media/android/media_resource_getter_impl.cc b/content/browser/media/android/media_resource_getter_impl.cc index 686e01c..99142e1 100644 --- a/content/browser/media/android/media_resource_getter_impl.cc +++ b/content/browser/media/android/media_resource_getter_impl.cc
@@ -28,6 +28,8 @@ #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_context_getter.h" #include "storage/browser/blob/blob_data_handle.h" +#include "storage/browser/blob/blob_data_item.h" +#include "storage/browser/blob/blob_data_snapshot.h" #include "storage/browser/blob/blob_storage_context.h" #include "url/gurl.h" @@ -59,18 +61,19 @@ ReturnResultOnUIThread(callback, std::string()); return; } - storage::BlobData* data = handle->data(); + scoped_ptr<storage::BlobDataSnapshot> data = handle->CreateSnapshot(); if (!data) { ReturnResultOnUIThread(callback, std::string()); NOTREACHED(); return; } - const std::vector<storage::BlobData::Item> items = data->items(); + const std::vector<scoped_refptr<storage::BlobDataItem>>& items = + data->items(); // TODO(qinmin): handle the case when the blob data is not a single file. DLOG_IF(WARNING, items.size() != 1u) - << "More than one blob data are present: " << items.size(); - ReturnResultOnUIThread(callback, items[0].path().value()); + << "More than one blob item is present: " << items.size(); + ReturnResultOnUIThread(callback, items[0]->path().value()); } static void RequestPlaformPathFromFileSystemURL(
diff --git a/content/browser/media/capture/desktop_capture_device_aura.cc b/content/browser/media/capture/desktop_capture_device_aura.cc index 8540040..60e4d57 100644 --- a/content/browser/media/capture/desktop_capture_device_aura.cc +++ b/content/browser/media/capture/desktop_capture_device_aura.cc
@@ -119,6 +119,7 @@ void OnCompositingEnded(ui::Compositor* compositor) override; void OnCompositingAborted(ui::Compositor* compositor) override {} void OnCompositingLockStateChanged(ui::Compositor* compositor) override {} + void OnCompositingShuttingDown(ui::Compositor* compositor) override {} private: // Captures a frame.
diff --git a/content/browser/media/capture/desktop_capture_device_aura_unittest.cc b/content/browser/media/capture/desktop_capture_device_aura_unittest.cc index 81cbd15b..6fcd680c 100644 --- a/content/browser/media/capture/desktop_capture_device_aura_unittest.cc +++ b/content/browser/media/capture/desktop_capture_device_aura_unittest.cc
@@ -57,10 +57,10 @@ public: DesktopCaptureDeviceAuraTest() : browser_thread_for_ui_(BrowserThread::UI, &message_loop_) {} - virtual ~DesktopCaptureDeviceAuraTest() {} + ~DesktopCaptureDeviceAuraTest() override {} protected: - virtual void SetUp() override { + void SetUp() override { // The ContextFactory must exist before any Compositors are created. bool enable_pixel_output = false; ui::ContextFactory* context_factory = @@ -82,7 +82,7 @@ desktop_window_->Show(); } - virtual void TearDown() override { + void TearDown() override { helper_->RunAllPendingInMessageLoop(); root_window()->RemoveChild(desktop_window_.get()); desktop_window_.reset();
diff --git a/content/browser/media/webrtc_browsertest.cc b/content/browser/media/webrtc_browsertest.cc index e40ec719..fc613c84 100644 --- a/content/browser/media/webrtc_browsertest.cc +++ b/content/browser/media/webrtc_browsertest.cc
@@ -175,11 +175,8 @@ MakeTypicalPeerConnectionCall("callAndSendDtmf(\'123,abc\');"); } -// TODO(phoglund): this test fails because the peer connection state will be -// stable in the second negotiation round rather than have-local-offer. -// http://crbug.com/293125. IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest, - DISABLED_CanMakeEmptyCallThenAddStreamsAndRenegotiate) { + CanMakeEmptyCallThenAddStreamsAndRenegotiate) { const char* kJavascript = "callEmptyThenAddOneStreamAndRenegotiate({video: true, audio: true});"; MakeTypicalPeerConnectionCall(kJavascript);
diff --git a/content/browser/message_port_message_filter.h b/content/browser/message_port_message_filter.h index 7acc141c..cdc8628 100644 --- a/content/browser/message_port_message_filter.h +++ b/content/browser/message_port_message_filter.h
@@ -6,16 +6,16 @@ #define CONTENT_BROWSER_MESSAGE_PORT_MESSAGE_FILTER_H_ #include "base/callback.h" -#include "content/browser/message_port_delegate.h" #include "content/common/content_export.h" #include "content/public/browser/browser_message_filter.h" +#include "content/public/browser/message_port_delegate.h" namespace content { // Filter for MessagePort related IPC messages (creating and destroying a // MessagePort, sending a message via a MessagePort etc). class CONTENT_EXPORT MessagePortMessageFilter - : NON_EXPORTED_BASE(public MessagePortDelegate), + : public MessagePortDelegate, public BrowserMessageFilter { public: typedef base::Callback<int(void)> NextRoutingIDCallback;
diff --git a/content/browser/message_port_provider.cc b/content/browser/message_port_provider.cc index 12be0653..0fd141db 100644 --- a/content/browser/message_port_provider.cc +++ b/content/browser/message_port_provider.cc
@@ -12,59 +12,77 @@ #include "content/browser/renderer_host/render_view_host_impl.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/common/view_messages.h" +#include "content/public/browser/message_port_delegate.h" namespace content { +namespace { + +void PostMessageOnIOThread(MessagePortMessageFilter* filter, + int routing_id, + ViewMsg_PostMessage_Params* params) { + if (!params->message_port_ids.empty()) { + filter->UpdateMessagePortsWithNewRoutes(params->message_port_ids, + ¶ms->new_routing_ids); + } + filter->Send(new ViewMsg_PostMessageEvent(routing_id, *params)); +} + +} // namespace + +// static void MessagePortProvider::PostMessageToFrame( WebContents* web_contents, const base::string16& source_origin, const base::string16& target_origin, const base::string16& data, const std::vector<int>& ports) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); - RenderViewHost* rvh = web_contents->GetRenderViewHost(); - if (!rvh) - return; + ViewMsg_PostMessage_Params* params = new ViewMsg_PostMessage_Params(); + params->is_data_raw_string = true; + params->data = data; + // Blink requires a source frame to transfer ports. This is why a + // source routing id is set here. See WebDOMMessageEvent::initMessageEvent() + params->source_routing_id = web_contents->GetRoutingID(); + params->source_origin = source_origin; + params->target_origin = target_origin; + params->message_port_ids = ports; - ViewMsg_PostMessage_Params params; - params.is_data_raw_string = true; - params.data = data; - params.source_routing_id = web_contents->GetRoutingID(); - params.source_origin = source_origin; - params.target_origin = target_origin; RenderProcessHostImpl* rph = - static_cast<RenderProcessHostImpl*>( - web_contents->GetRenderProcessHost()); + static_cast<RenderProcessHostImpl*>(web_contents->GetRenderProcessHost()); MessagePortMessageFilter* mf = rph->message_port_message_filter(); - - if (!ports.empty()) { - params.message_port_ids = ports; - mf->UpdateMessagePortsWithNewRoutes(params.message_port_ids, - ¶ms.new_routing_ids); - } - rvh->Send(new ViewMsg_PostMessageEvent( - web_contents->GetRenderViewHost()->GetRoutingID(), - params)); + BrowserThread::PostTask( + BrowserThread::IO, + FROM_HERE, + base::Bind(&PostMessageOnIOThread, + make_scoped_refptr(mf), + web_contents->GetRoutingID(), + base::Owned(params))); } -void MessagePortProvider::CreateMessageChannel(WebContents* web_contents, +// static +void MessagePortProvider::CreateMessageChannel(MessagePortDelegate* delegate, int* port1, int* port2) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - + DCHECK_CURRENTLY_ON(BrowserThread::IO); *port1 = 0; *port2 = 0; - - RenderProcessHostImpl* rph = - static_cast<RenderProcessHostImpl*>( - web_contents->GetRenderProcessHost()); - MessagePortMessageFilter* mf = rph->message_port_message_filter(); MessagePortService* msp = MessagePortService::GetInstance(); - msp->Create(mf->GetNextRoutingID(), mf, port1); - msp->Create(mf->GetNextRoutingID(), mf, port2); + msp->Create(MSG_ROUTING_NONE, delegate, port1); + msp->Create(MSG_ROUTING_NONE, delegate, port2); + // Update the routing number of the message ports to be equal to the message + // port numbers. + msp->UpdateMessagePort(*port1, delegate, *port1); + msp->UpdateMessagePort(*port2, delegate, *port2); msp->Entangle(*port1, *port2); msp->Entangle(*port2, *port1); } +// static +void MessagePortProvider::OnMessagePortDelegateClosing( + MessagePortDelegate* delegate) { + MessagePortService::GetInstance()->OnMessagePortDelegateClosing(delegate); +} + } // namespace content
diff --git a/content/browser/message_port_provider_browsertest.cc b/content/browser/message_port_provider_browsertest.cc new file mode 100644 index 0000000..3c9ea5d --- /dev/null +++ b/content/browser/message_port_provider_browsertest.cc
@@ -0,0 +1,142 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/bind.h" +#include "base/strings/utf_string_conversions.h" +#include "base/synchronization/waitable_event.h" +#include "content/browser/message_port_service.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/message_port_delegate.h" +#include "content/public/browser/message_port_provider.h" +#include "content/public/browser/web_contents.h" +#include "content/public/test/browser_test_utils.h" +#include "content/public/test/content_browser_test.h" +#include "content/public/test/content_browser_test_utils.h" +#include "content/shell/browser/shell.h" + +namespace content { + +// This test verifies the functionality of the Message Port Provider API. + +// A mock class for testing message port provider. +class MockMessagePortDelegate : public MessagePortDelegate { + public: + // A container to hold received messages + struct Message { + int route_id; // the routing id of the target port + base::string16 data; // the message data + std::vector<int> sent_ports; // any transferred ports + }; + + typedef std::vector<Message> Messages; + + MockMessagePortDelegate() { } + ~MockMessagePortDelegate() override { } + + // MessagePortDelegate implementation + void SendMessage(int route_id, + const base::string16& message, + const std::vector<int>& sent_message_port_ids) override { + Message m; + m.route_id = route_id; + m.data = message; + m.sent_ports = sent_message_port_ids; + messages_.push_back(m); + } + + void SendMessagesAreQueued(int route_id) override { } + + const Messages& getReceivedMessages() { + return messages_; + } + private: + Messages messages_; + + DISALLOW_COPY_AND_ASSIGN(MockMessagePortDelegate); +}; + + +class MessagePortProviderBrowserTest : public ContentBrowserTest { +}; + +// Verify that messages can be posted to main frame. +IN_PROC_BROWSER_TEST_F(MessagePortProviderBrowserTest, PostMessage) { + const std::string data = + "<!DOCTYPE html><html><body>" + " <script type=\"text/javascript\">" + " onmessage = function (e) { document.title = e.data; }" + " </script>" + "</body></html>"; + const base::string16 target_origin(base::UTF8ToUTF16("http://baseurl")); + const GURL base_url(target_origin); + const GURL history_url; + // Load data. Blocks until it is done. + content::LoadDataWithBaseURL(shell(), history_url, data, base_url); + const base::string16 source_origin(base::UTF8ToUTF16("source")); + const base::string16 message(base::UTF8ToUTF16("success")); + const std::vector<int> ports; + content::TitleWatcher title_watcher(shell()->web_contents(), message); + MessagePortProvider::PostMessageToFrame(shell()->web_contents(), + source_origin, + target_origin, + message, + ports); + EXPECT_EQ(message, title_watcher.WaitAndGetTitle()); +} + +namespace { + +void VerifyCreateChannelOnIOThread(base::WaitableEvent* event) { + + const base::char16 MESSAGE1[] = { 0x1000, 0 }; + const base::char16 MESSAGE2[] = { 0x1001, 0 }; + + MockMessagePortDelegate delegate; + int port1; + int port2; + + MessagePortProvider::CreateMessageChannel(&delegate, &port1, &port2); + MessagePortService* service = MessagePortService::GetInstance(); + // Send a message to port1 transferring no ports. + std::vector<int> sent_ports; + service->PostMessage(port1, base::string16(MESSAGE1), sent_ports); + // Verify that message is received + const MockMessagePortDelegate::Messages& received = + delegate.getReceivedMessages(); + EXPECT_EQ(received.size(), 1u); + // Verify that message sent to port1 is received by entangled port, which is + // port2. + EXPECT_EQ(received[0].route_id, port2); + EXPECT_EQ(received[0].data, MESSAGE1); + EXPECT_EQ(received[0].sent_ports.size(), 0u); + + // Create a new channel, and transfer one of its ports to port2, making sure + // the transferred port is received. + int port3; + int port4; + MessagePortProvider::CreateMessageChannel(&delegate, &port3, &port4); + sent_ports.push_back(port3); + service->PostMessage(port1, base::string16(MESSAGE2), sent_ports); + EXPECT_EQ(received.size(), 2u); + EXPECT_EQ(received[1].route_id, port2); + EXPECT_EQ(received[1].data, MESSAGE2); + EXPECT_EQ(received[1].sent_ports.size(), 1u); + EXPECT_EQ(received[1].sent_ports[0], port3); + + event->Signal(); +} + +} // namespace + +// Verify that a message channel can be created and used for exchanging +// messages. +IN_PROC_BROWSER_TEST_F(MessagePortProviderBrowserTest, CreateChannel) { + base::WaitableEvent event(true, false); + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(&VerifyCreateChannelOnIOThread, &event)); + event.Wait(); +} + +} // namespace content
diff --git a/content/browser/message_port_service.cc b/content/browser/message_port_service.cc index 42a30517..382f5b6 100644 --- a/content/browser/message_port_service.cc +++ b/content/browser/message_port_service.cc
@@ -4,9 +4,9 @@ #include "content/browser/message_port_service.h" -#include "content/browser/message_port_delegate.h" #include "content/common/message_port_messages.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/message_port_delegate.h" namespace content {
diff --git a/content/browser/message_port_service.h b/content/browser/message_port_service.h index 623b26b..5623e94 100644 --- a/content/browser/message_port_service.h +++ b/content/browser/message_port_service.h
@@ -12,12 +12,13 @@ #include "base/basictypes.h" #include "base/memory/singleton.h" #include "base/strings/string16.h" +#include "content/common/content_export.h" #include "ipc/ipc_message.h" namespace content { class MessagePortDelegate; -class MessagePortService { +class CONTENT_EXPORT MessagePortService { public: typedef std::vector<std::pair<base::string16, std::vector<int> > > QueuedMessages;
diff --git a/content/browser/mojo/mojo_application_host.cc b/content/browser/mojo/mojo_application_host.cc index 18219676..e5a9b0b 100644 --- a/content/browser/mojo/mojo_application_host.cc +++ b/content/browser/mojo/mojo_application_host.cc
@@ -7,7 +7,7 @@ #include "content/common/mojo/mojo_messages.h" #include "content/public/browser/browser_thread.h" #include "ipc/ipc_sender.h" -#include "mojo/edk/embedder/platform_channel_pair.h" +#include "third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h" namespace content { namespace {
diff --git a/content/browser/mojo/mojo_application_host.h b/content/browser/mojo/mojo_application_host.h index 0c02c49..53e150a 100644 --- a/content/browser/mojo/mojo_application_host.h +++ b/content/browser/mojo/mojo_application_host.h
@@ -8,8 +8,8 @@ #include "base/memory/scoped_ptr.h" #include "base/process/process_handle.h" #include "content/common/mojo/service_registry_impl.h" -#include "mojo/edk/embedder/channel_init.h" -#include "mojo/edk/embedder/scoped_platform_handle.h" +#include "third_party/mojo/src/mojo/edk/embedder/channel_init.h" +#include "third_party/mojo/src/mojo/edk/embedder/scoped_platform_handle.h" #if defined(OS_ANDROID) #include "content/browser/mojo/service_registry_android.h"
diff --git a/content/browser/navigator_connect/navigator_connect_context.cc b/content/browser/navigator_connect/navigator_connect_context.cc deleted file mode 100644 index 45d6a6f..0000000 --- a/content/browser/navigator_connect/navigator_connect_context.cc +++ /dev/null
@@ -1,91 +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 "content/browser/navigator_connect/navigator_connect_context.h" - -#include "content/browser/message_port_service.h" -#include "content/browser/service_worker/service_worker_context_wrapper.h" -#include "content/browser/service_worker/service_worker_utils.h" -#include "content/common/navigator_connect_types.h" - -namespace content { - -struct NavigatorConnectContext::Connection { - CrossOriginServiceWorkerClient client; - int64 service_worker_registration_id; - GURL service_worker_registration_origin; -}; - -NavigatorConnectContext::NavigatorConnectContext( - const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context) - : service_worker_context_(service_worker_context) { -} - -NavigatorConnectContext::~NavigatorConnectContext() { -} - -void NavigatorConnectContext::RegisterConnection( - const CrossOriginServiceWorkerClient& client, - const scoped_refptr<ServiceWorkerRegistration>& - service_worker_registration) { - MessagePortService::GetInstance()->UpdateMessagePort( - client.message_port_id, this, client.message_port_id); - MessagePortService::GetInstance()->ReleaseMessages(client.message_port_id); - Connection& connection = connections_[client.message_port_id]; - connection.client = client; - connection.service_worker_registration_id = service_worker_registration->id(); - connection.service_worker_registration_origin = - service_worker_registration->pattern().GetOrigin(); -} - -void NavigatorConnectContext::SendMessage( - int route_id, - const base::string16& message, - const std::vector<int>& sent_message_port_ids) { - DCHECK(connections_.find(route_id) != connections_.end()); - const Connection& connection = connections_[route_id]; - - // Hold messages while service worker is found, activated, and message sent - // causing ServiceWorkerScriptContext::OnCrossOriginMessageToWorker to - // construct WebMessagePortChannelImpl instances which send - // MessagePortHostMsg_ReleaseMessages. - for (int sent_message_port_id : sent_message_port_ids) - MessagePortService::GetInstance()->HoldMessages(sent_message_port_id); - - service_worker_context_->context()->storage()->FindRegistrationForId( - connection.service_worker_registration_id, - connection.service_worker_registration_origin, - base::Bind(&NavigatorConnectContext::DoSendMessage, this, - connection.client, message, sent_message_port_ids)); -} - -void NavigatorConnectContext::SendMessagesAreQueued(int route_id) { - NOTREACHED() << "navigator.connect endpoints should never queue messages."; -} - -void NavigatorConnectContext::DoSendMessage( - const CrossOriginServiceWorkerClient& client, - const base::string16& message, - const std::vector<int>& sent_message_port_ids, - ServiceWorkerStatusCode service_worker_status, - const scoped_refptr<ServiceWorkerRegistration>& - service_worker_registration) { - if (service_worker_status != SERVICE_WORKER_OK) { - // TODO(mek): Do something when no service worker was found. - return; - } - - ServiceWorkerVersion* active_version = - service_worker_registration->active_version(); - if (!active_version) { - // TODO(mek): Do something when no active version exists. - return; - } - - active_version->DispatchCrossOriginMessageEvent( - client, message, sent_message_port_ids, - base::Bind(&ServiceWorkerUtils::NoOpStatusCallback)); -} - -} // namespace content
diff --git a/content/browser/navigator_connect/navigator_connect_context.h b/content/browser/navigator_connect/navigator_connect_context.h deleted file mode 100644 index db4edbc..0000000 --- a/content/browser/navigator_connect/navigator_connect_context.h +++ /dev/null
@@ -1,66 +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 CONTENT_BROWSER_NAVIGATOR_CONNECT_NAVIGATOR_CONNECT_CONTEXT_H_ -#define CONTENT_BROWSER_NAVIGATOR_CONNECT_NAVIGATOR_CONNECT_CONTEXT_H_ - -#include <map> -#include "base/memory/ref_counted.h" -#include "content/browser/message_port_delegate.h" -#include "content/common/service_worker/service_worker_status_code.h" - -namespace content { - -struct CrossOriginServiceWorkerClient; -class ServiceWorkerContextWrapper; -class ServiceWorkerRegistration; - -// Tracks all active navigator.connect connections, wakes up service workers -// when a message arrives, and routes the messages. -// One instance of this class exists per StoragePartition. -// TODO(mek): Clean up message ports when a service worker is unregistered. -// TODO(mek): Somehow clean up connections when the client side goes away. -class NavigatorConnectContext - : public MessagePortDelegate, - public base::RefCountedThreadSafe<NavigatorConnectContext> { - public: - explicit NavigatorConnectContext( - const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context); - - // Registers an accepted connection and updates MessagePortService with the - // new route/delegate for the message port associated with this connection. - void RegisterConnection(const CrossOriginServiceWorkerClient& client, - const scoped_refptr<ServiceWorkerRegistration>& - service_worker_registration); - - // MessagePortDelegate implementation. For the implementation of this class, - // the route_id of a message port is always equal to the message_port_id. - void SendMessage(int route_id, - const base::string16& message, - const std::vector<int>& sent_message_port_ids) override; - void SendMessagesAreQueued(int route_id) override; - - private: - friend class base::RefCountedThreadSafe<NavigatorConnectContext>; - ~NavigatorConnectContext() override; - - // Callback called by SendMessage when a ServiceWorkerRegistration for the - // given message port has been located. - void DoSendMessage(const CrossOriginServiceWorkerClient& client, - const base::string16& message, - const std::vector<int>& sent_message_port_ids, - ServiceWorkerStatusCode service_worker_status, - const scoped_refptr<ServiceWorkerRegistration>& - service_worker_registration); - - scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_; - struct Connection; - // Maps route ids to connections. For the purpose of this class, the route id - // of a connection is the same as its message_port_id. - std::map<int, Connection> connections_; -}; - -} // namespace content - -#endif // CONTENT_BROWSER_NAVIGATOR_CONNECT_NAVIGATOR_CONNECT_CONTEXT_H_
diff --git a/content/browser/navigator_connect/navigator_connect_context_impl.cc b/content/browser/navigator_connect/navigator_connect_context_impl.cc new file mode 100644 index 0000000..91d8874 --- /dev/null +++ b/content/browser/navigator_connect/navigator_connect_context_impl.cc
@@ -0,0 +1,70 @@ +// 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 "content/browser/navigator_connect/navigator_connect_context_impl.h" + +#include "content/browser/message_port_service.h" +#include "content/public/browser/navigator_connect_service_factory.h" +#include "content/public/common/navigator_connect_client.h" + +namespace content { + +NavigatorConnectContextImpl::NavigatorConnectContextImpl() { +} + +NavigatorConnectContextImpl::~NavigatorConnectContextImpl() { +} + +void NavigatorConnectContextImpl::AddFactory( + scoped_ptr<NavigatorConnectServiceFactory> factory) { + service_factories_.push_back(factory.release()); +} + +void NavigatorConnectContextImpl::Connect(const NavigatorConnectClient& client, + const ConnectCallback& callback) { + // Hold messages for port while setting up connection. + MessagePortService::GetInstance()->HoldMessages(client.message_port_id); + + // Find factory to handle request, more recently added factories should take + // priority as per comment at NavigatorConnectContext::AddFactory.. + NavigatorConnectServiceFactory* factory = nullptr; + for (auto it = service_factories_.rbegin(); it != service_factories_.rend(); + ++it) { + if ((*it)->HandlesUrl(client.target_url)) { + factory = *it; + break; + } + } + + if (!factory) { + // No factories found. + // Close port since connection failed. + MessagePortService::GetInstance()->ClosePort(client.message_port_id); + callback.Run(false); + return; + } + + // Actually initiate connection. + factory->Connect( + client, base::Bind(&NavigatorConnectContextImpl::OnConnectResult, this, + client, callback)); +} + +void NavigatorConnectContextImpl::OnConnectResult( + const NavigatorConnectClient& client, + const ConnectCallback& callback, + MessagePortDelegate* delegate) { + if (delegate) { + MessagePortService::GetInstance()->UpdateMessagePort( + client.message_port_id, delegate, client.message_port_id); + MessagePortService::GetInstance()->ReleaseMessages(client.message_port_id); + callback.Run(true); + } else { + // Close port since connection failed. + MessagePortService::GetInstance()->ClosePort(client.message_port_id); + callback.Run(false); + } +} + +} // namespace content
diff --git a/content/browser/navigator_connect/navigator_connect_context_impl.h b/content/browser/navigator_connect/navigator_connect_context_impl.h new file mode 100644 index 0000000..8a983d5 --- /dev/null +++ b/content/browser/navigator_connect/navigator_connect_context_impl.h
@@ -0,0 +1,54 @@ +// 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 CONTENT_BROWSER_NAVIGATOR_CONNECT_NAVIGATOR_CONNECT_CONTEXT_IMPL_H_ +#define CONTENT_BROWSER_NAVIGATOR_CONNECT_NAVIGATOR_CONNECT_CONTEXT_IMPL_H_ + +#include <map> +#include "base/callback_forward.h" +#include "base/memory/scoped_vector.h" +#include "content/public/browser/message_port_delegate.h" +#include "content/public/browser/navigator_connect_context.h" + +namespace content { + +struct NavigatorConnectClient; +class NavigatorConnectService; +class NavigatorConnectServiceFactory; + +// Tracks all active navigator.connect connections, as well as available service +// factories. Delegates connection requests to the correct factory and passes +// messages on to the correct service. +// One instance of this class exists per StoragePartition. +// TODO(mek): Somehow clean up connections when the client side goes away. +class NavigatorConnectContextImpl : public NavigatorConnectContext { + public: + using ConnectCallback = base::Callback<void(bool success)>; + + explicit NavigatorConnectContextImpl(); + + // Called when a new connection request comes in from a client. Finds the + // correct service factory and passes the connection request off to there. + // Can call the callback before this method call returns. + void Connect(const NavigatorConnectClient& client, + const ConnectCallback& callback); + + // NavigatorConnectContext implementation. + void AddFactory(scoped_ptr<NavigatorConnectServiceFactory> factory) override; + + private: + ~NavigatorConnectContextImpl() override; + + // Callback called by service factories when a connection succeeded or failed. + void OnConnectResult(const NavigatorConnectClient& client, + const ConnectCallback& callback, + MessagePortDelegate* delegate); + + // List of factories to try to handle URLs. + ScopedVector<NavigatorConnectServiceFactory> service_factories_; +}; + +} // namespace content + +#endif // CONTENT_BROWSER_NAVIGATOR_CONNECT_NAVIGATOR_CONNECT_CONTEXT_IMPL_H_
diff --git a/content/browser/navigator_connect/navigator_connect_dispatcher_host.cc b/content/browser/navigator_connect/navigator_connect_dispatcher_host.cc index 3a4ae29..b65f4a5d 100644 --- a/content/browser/navigator_connect/navigator_connect_dispatcher_host.cc +++ b/content/browser/navigator_connect/navigator_connect_dispatcher_host.cc
@@ -5,18 +5,16 @@ #include "content/browser/navigator_connect/navigator_connect_dispatcher_host.h" #include "content/browser/message_port_service.h" -#include "content/browser/navigator_connect/navigator_connect_context.h" +#include "content/browser/navigator_connect/navigator_connect_context_impl.h" #include "content/browser/service_worker/service_worker_context_wrapper.h" #include "content/common/navigator_connect_messages.h" -#include "content/common/navigator_connect_types.h" +#include "content/public/common/navigator_connect_client.h" namespace content { NavigatorConnectDispatcherHost::NavigatorConnectDispatcherHost( - const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context, - const scoped_refptr<NavigatorConnectContext>& navigator_connect_context) + const scoped_refptr<NavigatorConnectContextImpl>& navigator_connect_context) : BrowserMessageFilter(NavigatorConnectMsgStart), - service_worker_context_(service_worker_context), navigator_connect_context_(navigator_connect_context) { } @@ -36,65 +34,21 @@ void NavigatorConnectDispatcherHost::OnConnect( int thread_id, int request_id, - const CrossOriginServiceWorkerClient& client) { + const NavigatorConnectClient& client) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - // Hold messages for port while setting up connection. - MessagePortService::GetInstance()->HoldMessages(client.message_port_id); - - // Find the right service worker to service this connection. - service_worker_context_->context()->storage()->FindRegistrationForDocument( - client.target_url, - base::Bind(&NavigatorConnectDispatcherHost::GotServiceWorkerRegistration, - this, thread_id, request_id, client)); -} - -void NavigatorConnectDispatcherHost::GotServiceWorkerRegistration( - int thread_id, - int request_id, - const CrossOriginServiceWorkerClient& client, - ServiceWorkerStatusCode status, - const scoped_refptr<ServiceWorkerRegistration>& registration) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - if (status != SERVICE_WORKER_OK) { - // No service worker found, reject connection attempt. - OnConnectResult(thread_id, request_id, client, registration, status, false); - return; - } - - ServiceWorkerVersion* active_version = registration->active_version(); - if (!active_version) { - // No active version, reject connection attempt. - OnConnectResult(thread_id, request_id, client, registration, status, false); - return; - } - - active_version->DispatchCrossOriginConnectEvent( - base::Bind(&NavigatorConnectDispatcherHost::OnConnectResult, this, - thread_id, request_id, client, registration), - client); + navigator_connect_context_->Connect( + client, base::Bind(&NavigatorConnectDispatcherHost::OnConnectResult, this, + thread_id, request_id)); } void NavigatorConnectDispatcherHost::OnConnectResult( int thread_id, int request_id, - const CrossOriginServiceWorkerClient& client, - const scoped_refptr<ServiceWorkerRegistration>& registration, - ServiceWorkerStatusCode status, bool accept_connection) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - - if (status != SERVICE_WORKER_OK || !accept_connection) { - // Close port since connection failed. - MessagePortService::GetInstance()->ClosePort(client.message_port_id); - Send(new NavigatorConnectMsg_ConnectResult(thread_id, request_id, false)); - return; - } - - // Register connection and post back result. - navigator_connect_context_->RegisterConnection(client, registration); - Send(new NavigatorConnectMsg_ConnectResult(thread_id, request_id, true)); + Send(new NavigatorConnectMsg_ConnectResult(thread_id, request_id, + accept_connection)); } } // namespace content
diff --git a/content/browser/navigator_connect/navigator_connect_dispatcher_host.h b/content/browser/navigator_connect/navigator_connect_dispatcher_host.h index 86350a7d..a41cbd7e 100644 --- a/content/browser/navigator_connect/navigator_connect_dispatcher_host.h +++ b/content/browser/navigator_connect/navigator_connect_dispatcher_host.h
@@ -5,17 +5,14 @@ #ifndef CONTENT_BROWSER_NAVIGATOR_CONNECT_NAVIGATOR_CONNECT_DISPATCHER_HOST_H_ #define CONTENT_BROWSER_NAVIGATOR_CONNECT_NAVIGATOR_CONNECT_DISPATCHER_HOST_H_ -#include "content/common/service_worker/service_worker_status_code.h" #include "content/public/browser/browser_message_filter.h" class GURL; namespace content { -struct CrossOriginServiceWorkerClient; -class NavigatorConnectContext; -class ServiceWorkerContextWrapper; -class ServiceWorkerRegistration; +struct NavigatorConnectClient; +class NavigatorConnectContextImpl; // Receives navigator.connect connection attempts from a child process. // Attempts to find a service that serves the URL the connection is made to @@ -27,9 +24,8 @@ // if it is still handling a connection attempt). class NavigatorConnectDispatcherHost : public BrowserMessageFilter { public: - NavigatorConnectDispatcherHost( - const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context, - const scoped_refptr<NavigatorConnectContext>& navigator_connect_context); + explicit NavigatorConnectDispatcherHost(const scoped_refptr< + NavigatorConnectContextImpl>& navigator_connect_context); private: ~NavigatorConnectDispatcherHost() override; @@ -40,29 +36,16 @@ // IPC Message handlers. void OnConnect(int thread_id, int request_id, - const CrossOriginServiceWorkerClient& client); - - // Callback called when the Service Worker context found (or didn't find) a - // service worker registration to serve a particular URL. - void GotServiceWorkerRegistration( - int thread_id, - int request_id, - const CrossOriginServiceWorkerClient& client, - ServiceWorkerStatusCode status, - const scoped_refptr<ServiceWorkerRegistration>& registration); + const NavigatorConnectClient& client); // Callback called when the service worker finished handling the cross origin // connection event. void OnConnectResult( int thread_id, int request_id, - const CrossOriginServiceWorkerClient& client, - const scoped_refptr<ServiceWorkerRegistration>& registration, - ServiceWorkerStatusCode status, bool accept_connection); - scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_; - scoped_refptr<NavigatorConnectContext> navigator_connect_context_; + scoped_refptr<NavigatorConnectContextImpl> navigator_connect_context_; DISALLOW_COPY_AND_ASSIGN(NavigatorConnectDispatcherHost); };
diff --git a/content/browser/navigator_connect/navigator_connect_service_worker_service_factory.cc b/content/browser/navigator_connect/navigator_connect_service_worker_service_factory.cc new file mode 100644 index 0000000..1fc27f3 --- /dev/null +++ b/content/browser/navigator_connect/navigator_connect_service_worker_service_factory.cc
@@ -0,0 +1,194 @@ +// Copyright 2015 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/navigator_connect/navigator_connect_service_worker_service_factory.h" + +#include "base/bind.h" +#include "content/browser/message_port_service.h" +#include "content/browser/service_worker/service_worker_context_wrapper.h" +#include "content/browser/service_worker/service_worker_utils.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/message_port_delegate.h" +#include "content/public/common/navigator_connect_client.h" + +namespace content { + +namespace { + +// MessagePortDelegate implementation that directs all messages to the +// oncrossoriginmessage event of a service worker. +// TODO(mek): Somehow clean up message ports when a service worker is +// unregistered. +class NavigatorConnectServiceWorkerService : public MessagePortDelegate { + public: + NavigatorConnectServiceWorkerService( + const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context, + const NavigatorConnectClient& client, + const scoped_refptr<ServiceWorkerRegistration>& + service_worker_registration); + ~NavigatorConnectServiceWorkerService() override; + + // MessagePortDelegate implementation. + void SendMessage(int route_id, + const base::string16& message, + const std::vector<int>& sent_message_port_ids) override; + void SendMessagesAreQueued(int route_id) override; + + private: + // Callback called by SendMessage when the ServiceWorkerRegistration for this + // service has been located. + void DeliverMessage(const base::string16& message, + const std::vector<int>& sent_message_port_ids, + ServiceWorkerStatusCode service_worker_status, + const scoped_refptr<ServiceWorkerRegistration>& + service_worker_registration); + + scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_; + NavigatorConnectClient client_; + int64 service_worker_registration_id_; + GURL service_worker_registration_origin_; + + base::WeakPtrFactory<NavigatorConnectServiceWorkerService> weak_factory_; +}; + +NavigatorConnectServiceWorkerService::NavigatorConnectServiceWorkerService( + const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context, + const NavigatorConnectClient& client, + const scoped_refptr<ServiceWorkerRegistration>& service_worker_registration) + : service_worker_context_(service_worker_context), + client_(client), + service_worker_registration_id_(service_worker_registration->id()), + service_worker_registration_origin_( + service_worker_registration->pattern().GetOrigin()), + weak_factory_(this) { +} + +NavigatorConnectServiceWorkerService::~NavigatorConnectServiceWorkerService() { +} + +void NavigatorConnectServiceWorkerService::SendMessage( + int route_id, + const base::string16& message, + const std::vector<int>& sent_message_port_ids) { + DCHECK(route_id == client_.message_port_id); + + // Hold messages on transferred message ports. Actual delivery of the message + // by the service can be asynchronous. When a message is delivered, + // WebMessagePortChannelImpl instances will be constructed which send + // MessagePortHostMsg_ReleaseMessages to release messages. + for (int sent_message_port_id : sent_message_port_ids) + MessagePortService::GetInstance()->HoldMessages(sent_message_port_id); + + service_worker_context_->context()->storage()->FindRegistrationForId( + service_worker_registration_id_, service_worker_registration_origin_, + base::Bind(&NavigatorConnectServiceWorkerService::DeliverMessage, + weak_factory_.GetWeakPtr(), message, sent_message_port_ids)); +} + +void NavigatorConnectServiceWorkerService::SendMessagesAreQueued(int route_id) { + NOTREACHED() << "navigator.connect endpoints should never queue messages."; +} + +void NavigatorConnectServiceWorkerService::DeliverMessage( + const base::string16& message, + const std::vector<int>& sent_message_port_ids, + ServiceWorkerStatusCode service_worker_status, + const scoped_refptr<ServiceWorkerRegistration>& + service_worker_registration) { + if (service_worker_status != SERVICE_WORKER_OK) { + // TODO(mek): Do something when no service worker was found. + return; + } + + ServiceWorkerVersion* active_version = + service_worker_registration->active_version(); + if (!active_version) { + // TODO(mek): Do something when no active version exists. + return; + } + + active_version->DispatchCrossOriginMessageEvent( + client_, message, sent_message_port_ids, + base::Bind(&ServiceWorkerUtils::NoOpStatusCallback)); +} + +} // namespace + +NavigatorConnectServiceWorkerServiceFactory:: + NavigatorConnectServiceWorkerServiceFactory(const scoped_refptr< + ServiceWorkerContextWrapper>& service_worker_context) + : service_worker_context_(service_worker_context), weak_factory_(this) { +} + +NavigatorConnectServiceWorkerServiceFactory:: + ~NavigatorConnectServiceWorkerServiceFactory() { +} + +bool NavigatorConnectServiceWorkerServiceFactory::HandlesUrl( + const GURL& target_url) { + // Always return true, all URLs could potentially have a service worker, and + // this factory will be installed as first factory, so it will only be used + // if no other factory claims to handle the url. + return true; +} + +void NavigatorConnectServiceWorkerServiceFactory::Connect( + const NavigatorConnectClient& client, + const ConnectCallback& callback) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + + // Find the right service worker to service this connection. + service_worker_context_->context()->storage()->FindRegistrationForDocument( + client.target_url, + base::Bind(&NavigatorConnectServiceWorkerServiceFactory:: + GotServiceWorkerRegistration, + weak_factory_.GetWeakPtr(), callback, client)); +} + +void NavigatorConnectServiceWorkerServiceFactory::GotServiceWorkerRegistration( + const ConnectCallback& callback, + const NavigatorConnectClient& client, + ServiceWorkerStatusCode status, + const scoped_refptr<ServiceWorkerRegistration>& registration) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + + if (status != SERVICE_WORKER_OK) { + // No service worker found, reject connection attempt. + OnConnectResult(callback, client, registration, status, false); + return; + } + + ServiceWorkerVersion* active_version = registration->active_version(); + if (!active_version) { + // No active version, reject connection attempt. + OnConnectResult(callback, client, registration, status, false); + return; + } + + active_version->DispatchCrossOriginConnectEvent( + base::Bind(&NavigatorConnectServiceWorkerServiceFactory::OnConnectResult, + weak_factory_.GetWeakPtr(), callback, client, registration), + client); +} + +void NavigatorConnectServiceWorkerServiceFactory::OnConnectResult( + const ConnectCallback& callback, + const NavigatorConnectClient& client, + const scoped_refptr<ServiceWorkerRegistration>& service_worker_registration, + ServiceWorkerStatusCode status, + bool accept_connection) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + + if (status != SERVICE_WORKER_OK || !accept_connection) { + callback.Run(nullptr); + return; + } + + // TODO(mek): Keep track of NavigatorConnectServiceWorkerService instances and + // clean them up when a service worker registration is deleted. + callback.Run(new NavigatorConnectServiceWorkerService( + service_worker_context_, client, service_worker_registration)); +} + +} // namespace content
diff --git a/content/browser/navigator_connect/navigator_connect_service_worker_service_factory.h b/content/browser/navigator_connect/navigator_connect_service_worker_service_factory.h new file mode 100644 index 0000000..4e0239f --- /dev/null +++ b/content/browser/navigator_connect/navigator_connect_service_worker_service_factory.h
@@ -0,0 +1,61 @@ +// Copyright 2015 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_NAVIGATOR_CONNECT_NAVIGATOR_CONNECT_SERVICE_WORKER_SERVICE_FACTORY_H_ +#define CONTENT_BROWSER_NAVIGATOR_CONNECT_NAVIGATOR_CONNECT_SERVICE_WORKER_SERVICE_FACTORY_H_ + +#include <map> + +#include "base/memory/weak_ptr.h" +#include "content/common/service_worker/service_worker_status_code.h" +#include "content/public/browser/navigator_connect_service_factory.h" + +namespace content { + +class ServiceWorkerContextWrapper; +class ServiceWorkerRegistration; + +// Service worker specific NavigatorConnectServiceFactory implementation. This +// class accepts all URLs (and thus has to be the first factory to be added to +// NavigatorConnectContext or no other factories will ever by used). +// Tries to find a service worker registration to handle the url being connected +// to. +class NavigatorConnectServiceWorkerServiceFactory + : public NavigatorConnectServiceFactory { + public: + explicit NavigatorConnectServiceWorkerServiceFactory( + const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context); + ~NavigatorConnectServiceWorkerServiceFactory() override; + + // NavigatorConnectServiceFactory implementation. + bool HandlesUrl(const GURL& target_url) override; + void Connect(const NavigatorConnectClient& client, + const ConnectCallback& callback) override; + + private: + // Callback called when the Service Worker context found (or didn't find) a + // service worker registration to serve a particular URL. + void GotServiceWorkerRegistration( + const ConnectCallback& callback, + const NavigatorConnectClient& client, + ServiceWorkerStatusCode status, + const scoped_refptr<ServiceWorkerRegistration>& registration); + + // Callback called when the service worker finished handling the cross origin + // connection event. + void OnConnectResult( + const ConnectCallback& callback, + const NavigatorConnectClient& client, + const scoped_refptr<ServiceWorkerRegistration>& registration, + ServiceWorkerStatusCode status, + bool accept_connection); + + scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_; + base::WeakPtrFactory<NavigatorConnectServiceWorkerServiceFactory> + weak_factory_; +}; + +} // namespace content + +#endif // CONTENT_BROWSER_NAVIGATOR_CONNECT_NAVIGATOR_CONNECT_SERVICE_WORKER_SERVICE_FACTORY_H_
diff --git a/content/browser/net/sqlite_persistent_cookie_store.cc b/content/browser/net/sqlite_persistent_cookie_store.cc index b4ab241..cb2f98ea 100644 --- a/content/browser/net/sqlite_persistent_cookie_store.cc +++ b/content/browser/net/sqlite_persistent_cookie_store.cc
@@ -50,7 +50,10 @@ // The persistent cookie store is loaded into memory on eTLD at a time. This // variable controls the delay between loading eTLDs, so as to not overload the // CPU or I/O with these low priority requests immediately after start up. -const int kLoadDelayMilliseconds = 200; +// TODO(erikchen): Investigate why setting this value to 200 causes hangs on +// shut down. +// http://crbug.com/448910 +const int kLoadDelayMilliseconds = 0; } // namespace
diff --git a/content/browser/net_info_browsertest.cc b/content/browser/net_info_browsertest.cc index cea6962..fb805f3 100644 --- a/content/browser/net_info_browsertest.cc +++ b/content/browser/net_info_browsertest.cc
@@ -21,7 +21,7 @@ } #if defined(OS_CHROMEOS) - virtual void SetUp() override { + void SetUp() override { // ChromeOS's NetworkChangeNotifier isn't known to content and therefore // doesn't get created in content_browsertests. Insert a mock // NetworkChangeNotifier.
diff --git a/content/browser/permissions/permission_service_context.h b/content/browser/permissions/permission_service_context.h index 1e71958..c14b40c 100644 --- a/content/browser/permissions/permission_service_context.h +++ b/content/browser/permissions/permission_service_context.h
@@ -8,7 +8,7 @@ #include "base/macros.h" #include "base/memory/scoped_vector.h" #include "content/public/browser/web_contents_observer.h" -#include "mojo/public/cpp/bindings/interface_request.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h" namespace content {
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc index f62717f..e1edf05 100644 --- a/content/browser/renderer_host/compositor_impl_android.cc +++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -239,7 +239,7 @@ delay = next_composite - now; } } - TRACE_EVENT2("cc", "CompositorImpl::PostComposite", + TRACE_EVENT2("cc,benchmark", "CompositorImpl::PostComposite", "trigger", trigger, "delay", delay.InMillisecondsF());
diff --git a/content/browser/renderer_host/frame_metadata_util.cc b/content/browser/renderer_host/frame_metadata_util.cc new file mode 100644 index 0000000..11cf5d2 --- /dev/null +++ b/content/browser/renderer_host/frame_metadata_util.cc
@@ -0,0 +1,39 @@ +// 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. + +#include "content/browser/renderer_host/frame_metadata_util.h" + +#include "cc/output/compositor_frame_metadata.h" + +namespace { + +// Used to accomodate finite precision when comparing scaled viewport and +// content widths. While this value may seem large, width=device-width on an N7 +// V1 saw errors of ~0.065 between computed window and content widths. +const float kMobileViewportWidthEpsilon = 0.15f; + +bool HasFixedPageScale(const cc::CompositorFrameMetadata& frame_metadata) { + return frame_metadata.min_page_scale_factor == + frame_metadata.max_page_scale_factor; +} + +bool HasMobileViewport(const cc::CompositorFrameMetadata& frame_metadata) { + float window_width_dip = + frame_metadata.page_scale_factor * + frame_metadata.scrollable_viewport_size.width(); + float content_width_css = frame_metadata.root_layer_size.width(); + return content_width_css <= window_width_dip + kMobileViewportWidthEpsilon; +} + +} // namespace + +namespace content { + +bool IsMobileOptimizedFrame(const cc::CompositorFrameMetadata& frame_metadata) { + bool has_mobile_viewport = HasMobileViewport(frame_metadata); + bool has_fixed_page_scale = HasFixedPageScale(frame_metadata); + return has_fixed_page_scale || has_mobile_viewport; +} + +} // namespace content
diff --git a/content/browser/renderer_host/frame_metadata_util.h b/content/browser/renderer_host/frame_metadata_util.h new file mode 100644 index 0000000..54b97b8 --- /dev/null +++ b/content/browser/renderer_host/frame_metadata_util.h
@@ -0,0 +1,26 @@ +// 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 CONTENT_BROWSER_RENDERER_HOST_FRAME_METADATA_UTIL_H_ +#define CONTENT_BROWSER_RENDERER_HOST_FRAME_METADATA_UTIL_H_ + +#include "content/common/content_export.h" + +namespace cc { +class CompositorFrameMetadata; +} + +namespace content { + +// Decides whether frame metadata corresponds to mobile-optimized content. +// By default returns |false|, except for the following cases: +// - page that has a width=device-width or narrower viewport +// (indicating that this is a mobile-optimized or responsive web design); +// - page that prevents zooming in or out. +CONTENT_EXPORT bool IsMobileOptimizedFrame( + const cc::CompositorFrameMetadata& frame_metadata); + +} // namespace content + +#endif // CONTENT_BROWSER_RENDERER_HOST_FRAME_METADATA_UTIL_H_
diff --git a/content/browser/renderer_host/gamepad_browser_message_filter.cc b/content/browser/renderer_host/gamepad_browser_message_filter.cc index ef66a5c..c03e4788 100644 --- a/content/browser/renderer_host/gamepad_browser_message_filter.cc +++ b/content/browser/renderer_host/gamepad_browser_message_filter.cc
@@ -46,14 +46,20 @@ void GamepadBrowserMessageFilter::OnGamepadStartPolling( base::SharedMemoryHandle* renderer_handle) { GamepadService* service = GamepadService::GetInstance(); - CHECK(!is_started_); + DCHECK(!is_started_); + if (is_started_) + return; + is_started_ = true; service->ConsumerBecameActive(this); *renderer_handle = service->GetSharedMemoryHandleForProcess(PeerHandle()); } void GamepadBrowserMessageFilter::OnGamepadStopPolling() { - CHECK(is_started_); + DCHECK(is_started_); + if (!is_started_) + return; + is_started_ = false; GamepadService::GetInstance()->ConsumerBecameInactive(this); }
diff --git a/content/browser/renderer_host/input/touch_emulator.cc b/content/browser/renderer_host/input/touch_emulator.cc index 8592bd2..ec6057b 100644 --- a/content/browser/renderer_host/input/touch_emulator.cc +++ b/content/browser/renderer_host/input/touch_emulator.cc
@@ -47,6 +47,7 @@ : client_(client), gesture_provider_config_type_( ui::GestureProviderConfigType::CURRENT_PLATFORM), + double_tap_enabled_(true), emulated_stream_active_sequence_count_(0), native_stream_active_sequence_count_(0) { DCHECK(client_); @@ -92,9 +93,7 @@ GetEmulatorGestureProviderConfig(config_type), this)); // TODO(dgozman): Use synthetic secondary touch to support multi-touch. gesture_provider_->SetMultiTouchZoomSupportEnabled(false); - // TODO(dgozman): Enable double tap if requested by the renderer. - // TODO(dgozman): Don't break double-tap-based pinch with shift handling. - gesture_provider_->SetDoubleTapSupportForPlatformEnabled(false); + gesture_provider_->SetDoubleTapSupportForPageEnabled(double_tap_enabled_); } UpdateCursor(); } @@ -109,6 +108,12 @@ ResetState(); } +void TouchEmulator::SetDoubleTapSupportForPageEnabled(bool enabled) { + double_tap_enabled_ = enabled; + if (gesture_provider_) + gesture_provider_->SetDoubleTapSupportForPageEnabled(enabled); +} + gfx::SizeF TouchEmulator::InitCursorFromResource( WebCursor* cursor, float scale, int resource_id) { gfx::Image& cursor_image = @@ -331,7 +336,7 @@ } void TouchEmulator::CancelTouch() { - if (!emulated_stream_active_sequence_count_) + if (!emulated_stream_active_sequence_count_ || !enabled()) return; WebTouchEventTraits::ResetTypeAndTouchStates(
diff --git a/content/browser/renderer_host/input/touch_emulator.h b/content/browser/renderer_host/input/touch_emulator.h index f7d53dd..87c985d3 100644 --- a/content/browser/renderer_host/input/touch_emulator.h +++ b/content/browser/renderer_host/input/touch_emulator.h
@@ -24,6 +24,9 @@ void Enable(ui::GestureProviderConfigType config_type); void Disable(); + // See GestureProvider::SetDoubleTapSupportForPageEnabled. + void SetDoubleTapSupportForPageEnabled(bool enabled); + // Note that TouchEmulator should always listen to touch events and their acks // (even in disabled state) to track native stream presence. bool enabled() const { return gesture_provider_; } @@ -78,6 +81,7 @@ // emulation. It does not intercept any events. scoped_ptr<ui::FilteredGestureProvider> gesture_provider_; ui::GestureProviderConfigType gesture_provider_config_type_; + bool double_tap_enabled_; // While emulation is on, default cursor is touch. Pressing shift changes // cursor to the pinch one.
diff --git a/content/browser/renderer_host/input/touch_emulator_unittest.cc b/content/browser/renderer_host/input/touch_emulator_unittest.cc index 09441af..4b8bd1d 100644 --- a/content/browser/renderer_host/input/touch_emulator_unittest.cc +++ b/content/browser/renderer_host/input/touch_emulator_unittest.cc
@@ -53,6 +53,7 @@ #endif emulator_.reset(new TouchEmulator(this)); + emulator_->SetDoubleTapSupportForPageEnabled(false); emulator_->Enable(ui::GestureProviderConfigType::GENERIC_MOBILE); } @@ -283,6 +284,20 @@ ExpectedEvents()); } +TEST_F(TouchEmulatorTest, DoubleTapSupport) { + emulator()->SetDoubleTapSupportForPageEnabled(true); + MouseMove(100, 200); + EXPECT_EQ("", ExpectedEvents()); + MouseDown(100, 200); + EXPECT_EQ("TouchStart GestureTapDown", ExpectedEvents()); + MouseUp(100, 200); + EXPECT_EQ("TouchEnd GestureTapUnconfirmed", ExpectedEvents()); + MouseDown(100, 200); + EXPECT_EQ("TouchStart GestureTapCancel GestureTapDown", ExpectedEvents()); + MouseUp(100, 200); + EXPECT_EQ("TouchEnd GestureTapCancel GestureDoubleTap", ExpectedEvents()); +} + TEST_F(TouchEmulatorTest, MultipleTouches) { MouseMove(100, 200); EXPECT_EQ("", ExpectedEvents()); @@ -552,4 +567,12 @@ ExpectedEvents()); } +TEST_F(TouchEmulatorTest, CancelAfterDisableDoesNotCrash) { + DisableSynchronousTouchAck(); + MouseDown(100, 200); + emulator()->Disable(); + EXPECT_EQ("TouchStart TouchCancel", ExpectedEvents()); + emulator()->CancelTouch(); +} + } // namespace content
diff --git a/content/browser/renderer_host/p2p/socket_host.cc b/content/browser/renderer_host/p2p/socket_host.cc index 6358eff..bc54d400 100644 --- a/content/browser/renderer_host/p2p/socket_host.cc +++ b/content/browser/renderer_host/p2p/socket_host.cc
@@ -141,12 +141,11 @@ return; } - // Now() has resolution ~1-15ms, using HighResNow(). But it is warned not to - // use it unless necessary, as it is expensive than Now(). + // Now() has resolution ~1-15ms uint32 now_second = abs_send_time; if (!now_second) { uint64 now_us = - (base::TimeTicks::HighResNow() - base::TimeTicks()).InMicroseconds(); + (base::TimeTicks::Now() - base::TimeTicks()).InMicroseconds(); // Convert second to 24-bit unsigned with 18 bit fractional part now_second = ((now_us << 18) / base::Time::kMicrosecondsPerSecond) & 0x00FFFFFF;
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index e663ff0..e17c792 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -67,7 +67,6 @@ #include "content/browser/message_port_message_filter.h" #include "content/browser/mime_registry_message_filter.h" #include "content/browser/mojo/mojo_application_host.h" -#include "content/browser/navigator_connect/navigator_connect_context.h" #include "content/browser/navigator_connect/navigator_connect_dispatcher_host.h" #include "content/browser/notifications/notification_message_filter.h" #include "content/browser/permissions/permission_service_context.h" @@ -115,6 +114,7 @@ #include "content/common/view_messages.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/content_browser_client.h" +#include "content/public/browser/navigator_connect_context.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/notification_types.h" #include "content/public/browser/render_process_host_factory.h" @@ -459,6 +459,7 @@ within_process_died_observer_(false), power_monitor_broadcaster_(this), worker_ref_count_(0), + max_worker_count_(0), permission_service_context_(new PermissionServiceContext(this)), pending_valuebuffer_state_(new gpu::ValueStateMap()), subscribe_uniform_enabled_(false), @@ -564,14 +565,12 @@ return true; base::CommandLine::StringType renderer_prefix; -#if defined(OS_POSIX) // A command prefix is something prepended to the command line of the spawned - // process. It is supported only on POSIX systems. + // process. const base::CommandLine& browser_command_line = *base::CommandLine::ForCurrentProcess(); renderer_prefix = browser_command_line.GetSwitchValueNative(switches::kRendererCmdPrefix); -#endif // defined(OS_POSIX) #if defined(OS_LINUX) int flags = renderer_prefix.empty() ? ChildProcessHost::CHILD_ALLOW_SELF : @@ -888,7 +887,6 @@ AddFilter(new GeofencingDispatcherHost( storage_partition_impl_->GetGeofencingManager())); AddFilter(new NavigatorConnectDispatcherHost( - storage_partition_impl_->GetServiceWorkerContext(), storage_partition_impl_->GetNavigatorConnectContext())); if (browser_command_line.HasSwitch( switches::kEnableExperimentalWebPlatformFeatures)) { @@ -1073,10 +1071,11 @@ command_line->AppendSwitch(switches::kEnableDelegatedRenderer); if (IsImplSidePaintingEnabled()) { - command_line->AppendSwitch(switches::kEnableImplSidePainting); command_line->AppendSwitchASCII( switches::kNumRasterThreads, base::IntToString(NumberOfRendererRasterThreads())); + } else { + command_line->AppendSwitch(switches::kDisableImplSidePainting); } if (IsGpuRasterizationEnabled()) @@ -1194,6 +1193,7 @@ switches::kDisableDirectNPAPIRequests, switches::kDisableDisplayList2dCanvas, switches::kDisableDistanceFieldText, + switches::kDisableEncryptedMedia, switches::kDisableFileSystem, switches::kDisableGpuCompositing, switches::kDisableGpuVsync, @@ -1225,7 +1225,6 @@ switches::kEnableDelayAgnosticAec, switches::kEnableDisplayList2dCanvas, switches::kEnableDistanceFieldText, - switches::kEnableEncryptedMedia, switches::kEnableExperimentalCanvasFeatures, switches::kEnableExperimentalWebPlatformFeatures, switches::kEnableGPUClientLogging, @@ -1596,6 +1595,14 @@ "SharedWorker.RendererSurviveForWorkerTime", base::TimeTicks::Now() - survive_for_worker_start_time_); } + + if (max_worker_count_ > 0) { + // Record the max number of workers (SharedWorker or ServiceWorker) + // that are simultaneously hosted in this renderer process. + UMA_HISTOGRAM_COUNTS("Render.Workers.MaxWorkerCountInRendererProcess", + max_worker_count_); + } + // We cannot clean up twice; if this fails, there is an issue with our // control flow. DCHECK(!deleting_soon_); @@ -2357,6 +2364,8 @@ void RenderProcessHostImpl::IncrementWorkerRefCount() { DCHECK_CURRENTLY_ON(BrowserThread::UI); ++worker_ref_count_; + if (worker_ref_count_ > max_worker_count_) + max_worker_count_ = worker_ref_count_; } void RenderProcessHostImpl::DecrementWorkerRefCount() {
diff --git a/content/browser/renderer_host/render_process_host_impl.h b/content/browser/renderer_host/render_process_host_impl.h index 690ccef..7be2c60a 100644 --- a/content/browser/renderer_host/render_process_host_impl.h +++ b/content/browser/renderer_host/render_process_host_impl.h
@@ -20,7 +20,7 @@ #include "content/public/browser/render_process_host.h" #include "ipc/ipc_channel_proxy.h" #include "ipc/ipc_platform_file.h" -#include "mojo/public/cpp/bindings/interface_ptr.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_ptr.h" #include "ui/gfx/gpu_memory_buffer.h" #include "ui/gl/gpu_switching_observer.h" @@ -476,6 +476,10 @@ // Records the time when the process starts surviving for workers for UMA. base::TimeTicks survive_for_worker_start_time_; + // Records the maximum # of workers simultaneously hosted in this process + // for UMA. + int max_worker_count_; + // Context shared for each PermissionService instance created for this RPH. scoped_ptr<PermissionServiceContext> permission_service_context_;
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc index 5e49b1f0..4b90f73 100644 --- a/content/browser/renderer_host/render_widget_host_impl.cc +++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -32,6 +32,7 @@ #include "content/browser/gpu/gpu_process_host_ui_shim.h" #include "content/browser/gpu/gpu_surface_tracker.h" #include "content/browser/renderer_host/dip_util.h" +#include "content/browser/renderer_host/frame_metadata_util.h" #include "content/browser/renderer_host/input/input_router_config_helper.h" #include "content/browser/renderer_host/input/input_router_impl.h" #include "content/browser/renderer_host/input/synthetic_gesture.h" @@ -1437,8 +1438,7 @@ const IPC::Message& message) { // This trace event is used in // chrome/browser/extensions/api/cast_streaming/performance_test.cc - TRACE_EVENT0("test_fps", - TRACE_DISABLED_BY_DEFAULT("OnSwapCompositorFrame")); + TRACE_EVENT0("test_fps,benchmark", "OnSwapCompositorFrame"); ViewHostMsg_SwapCompositorFrame::Param param; if (!ViewHostMsg_SwapCompositorFrame::Read(&message, ¶m)) return false; @@ -1453,6 +1453,11 @@ input_router_->OnViewUpdated( GetInputRouterViewFlagsFromCompositorFrameMetadata(frame->metadata)); + if (touch_emulator_) { + touch_emulator_->SetDoubleTapSupportForPageEnabled( + !IsMobileOptimizedFrame(frame->metadata)); + } + if (view_) { view_->OnSwapCompositorFrame(output_surface_id, frame.Pass()); view_->DidReceiveRendererFrame();
diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h index a6debc3..99f2aa3 100644 --- a/content/browser/renderer_host/render_widget_host_impl.h +++ b/content/browser/renderer_host/render_widget_host_impl.h
@@ -403,9 +403,6 @@ bool GotResponseToLockMouseRequest(bool allowed); // Tells the RenderWidget about the latest vsync parameters. - // Note: Make sure the timebase was obtained using - // base::TimeTicks::HighResNow. Using the non-high res timer will result in - // incorrect synchronization across processes. virtual void UpdateVSyncParameters(base::TimeTicks timebase, base::TimeDelta interval);
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 20d45e12..fde64ae 100644 --- a/content/browser/renderer_host/render_widget_host_view_android.cc +++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -44,6 +44,7 @@ #include "content/browser/media/media_web_contents_observer.h" #include "content/browser/renderer_host/compositor_impl_android.h" #include "content/browser/renderer_host/dip_util.h" +#include "content/browser/renderer_host/frame_metadata_util.h" #include "content/browser/renderer_host/input/synthetic_gesture_target_android.h" #include "content/browser/renderer_host/input/web_input_event_builders_android.h" #include "content/browser/renderer_host/input/web_input_event_util.h" @@ -88,11 +89,6 @@ const int kUndefinedOutputSurfaceId = -1; -// Used to accomodate finite precision when comparing scaled viewport and -// content widths. While this value may seem large, width=device-width on an N7 -// V1 saw errors of ~0.065 between computed window and content widths. -const float kMobileViewportWidthEpsilon = 0.15f; - static const char kAsyncReadBackString[] = "Compositing.CopyFromSurfaceTime"; // Sends an acknowledgement to the renderer of a processed IME event. @@ -293,19 +289,6 @@ return config; } -bool HasFixedPageScale(const cc::CompositorFrameMetadata& frame_metadata) { - return frame_metadata.min_page_scale_factor == - frame_metadata.max_page_scale_factor; -} - -bool HasMobileViewport(const cc::CompositorFrameMetadata& frame_metadata) { - float window_width_dip = - frame_metadata.page_scale_factor * - frame_metadata.scrollable_viewport_size.width(); - float content_width_css = frame_metadata.root_layer_size.width(); - return content_width_css <= window_width_dip + kMobileViewportWidthEpsilon; -} - } // anonymous namespace ReadbackRequest::ReadbackRequest(float scale, @@ -1017,10 +1000,8 @@ cc::CompositorFrameAck ack; if (resource_collection_.get()) resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources); - RenderWidgetHostImpl::SendSwapCompositorFrameAck(host_->GetRoutingID(), - output_surface_id, - host_->GetProcess()->GetID(), - ack); + host_->Send(new ViewMsg_SwapCompositorFrameAck(host_->GetRoutingID(), + output_surface_id, ack)); } void RenderWidgetHostViewAndroid::SendReturnedDelegatedResources( @@ -1031,11 +1012,8 @@ resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources); DCHECK(!ack.resources.empty()); - RenderWidgetHostImpl::SendReclaimCompositorResources( - host_->GetRoutingID(), - output_surface_id, - host_->GetProcess()->GetID(), - ack); + host_->Send(new ViewMsg_ReclaimCompositorResources(host_->GetRoutingID(), + output_surface_id, ack)); } void RenderWidgetHostViewAndroid::UnusedResourcesAreAvailable() { @@ -1332,15 +1310,8 @@ void RenderWidgetHostViewAndroid::OnFrameMetadataUpdated( const cc::CompositorFrameMetadata& frame_metadata) { - - // Disable double tap zoom for pages that have a width=device-width or - // narrower viewport (indicating that this is a mobile-optimized or responsive - // web design, so text will be legible without zooming). Also disable - // double tap and pinch for pages that prevent zooming in or out. - bool has_mobile_viewport = HasMobileViewport(frame_metadata); - bool has_fixed_page_scale = HasFixedPageScale(frame_metadata); gesture_provider_.SetDoubleTapSupportForPageEnabled( - !has_fixed_page_scale && !has_mobile_viewport); + !IsMobileOptimizedFrame(frame_metadata)); if (!content_view_core_) return; @@ -1776,7 +1747,7 @@ void RenderWidgetHostViewAndroid::OnVSync(base::TimeTicks frame_time, base::TimeDelta vsync_period) { - TRACE_EVENT0("cc", "RenderWidgetHostViewAndroid::OnVSync"); + TRACE_EVENT0("cc,benchmark", "RenderWidgetHostViewAndroid::OnVSync"); if (!host_) return;
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc index d75bbce..27cb755 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -2519,7 +2519,7 @@ reinterpret_cast<HWND>(GetNativeViewId())); #endif - delegated_frame_host_->AddedToWindow(); + delegated_frame_host_->SetCompositor(window_->GetHost()->compositor()); } void RenderWidgetHostViewAura::RemovingFromRootWindow() { @@ -2531,7 +2531,7 @@ DetachFromInputMethod(); window_->GetHost()->RemoveObserver(this); - delegated_frame_host_->RemovingFromWindow(); + delegated_frame_host_->ResetCompositor(); #if defined(OS_WIN) // Update the legacy window's parent temporarily to the desktop window. It @@ -2583,37 +2583,35 @@ //////////////////////////////////////////////////////////////////////////////// // DelegatedFrameHost, public: -ui::Compositor* RenderWidgetHostViewAura::GetCompositor() const { - aura::WindowTreeHost* host = window_->GetHost(); - return host ? host->compositor() : NULL; -} - -ui::Layer* RenderWidgetHostViewAura::GetLayer() { +ui::Layer* RenderWidgetHostViewAura::DelegatedFrameHostGetLayer() const { return window_->layer(); } -RenderWidgetHostImpl* RenderWidgetHostViewAura::GetHost() { - return host_; +bool RenderWidgetHostViewAura::DelegatedFrameHostIsVisible() const { + return !host_->is_hidden(); } -bool RenderWidgetHostViewAura::IsVisible() { - return IsShowing(); -} - -gfx::Size RenderWidgetHostViewAura::DesiredFrameSize() { +gfx::Size RenderWidgetHostViewAura::DelegatedFrameHostDesiredSizeInDIP() const { return window_->bounds().size(); } -float RenderWidgetHostViewAura::CurrentDeviceScaleFactor() { - return current_device_scale_factor_; +bool RenderWidgetHostViewAura::DelegatedFrameCanCreateResizeLock() const { +#if !defined(OS_CHROMEOS) + // On Windows and Linux, holding pointer moves will not help throttling + // resizes. + // TODO(piman): on Windows we need to block (nested message loop?) the + // WM_SIZE event. On Linux we need to throttle at the WM level using + // _NET_WM_SYNC_REQUEST. + return false; +#else + if (host_->auto_resize_enabled()) + return false; + return true; +#endif } -gfx::Size RenderWidgetHostViewAura::ConvertViewSizeToPixel( - const gfx::Size& size) { - return content::ConvertViewSizeToPixel(this, size); -} - -scoped_ptr<ResizeLock> RenderWidgetHostViewAura::CreateResizeLock( +scoped_ptr<ResizeLock> +RenderWidgetHostViewAura::DelegatedFrameHostCreateResizeLock( bool defer_compositor_lock) { gfx::Size desired_size = window_->bounds().size(); return scoped_ptr<ResizeLock>(new CompositorResizeLock( @@ -2623,8 +2621,32 @@ base::TimeDelta::FromMilliseconds(kResizeLockTimeoutMs))); } -DelegatedFrameHost* RenderWidgetHostViewAura::GetDelegatedFrameHost() const { - return delegated_frame_host_.get(); +void RenderWidgetHostViewAura::DelegatedFrameHostResizeLockWasReleased() { + host_->WasResized(); +} + +void RenderWidgetHostViewAura::DelegatedFrameHostSendCompositorSwapAck( + int output_surface_id, + const cc::CompositorFrameAck& ack) { + host_->Send(new ViewMsg_SwapCompositorFrameAck(host_->GetRoutingID(), + output_surface_id, ack)); +} + +void RenderWidgetHostViewAura::DelegatedFrameHostSendReclaimCompositorResources( + int output_surface_id, + const cc::CompositorFrameAck& ack) { + host_->Send(new ViewMsg_ReclaimCompositorResources(host_->GetRoutingID(), + output_surface_id, ack)); +} + +void RenderWidgetHostViewAura::DelegatedFrameHostOnLostCompositorResources() { + host_->ScheduleComposite(); +} + +void RenderWidgetHostViewAura::DelegatedFrameHostUpdateVSyncParameters( + const base::TimeTicks& timebase, + const base::TimeDelta& interval) { + host_->UpdateVSyncParameters(timebase, interval); } ////////////////////////////////////////////////////////////////////////////////
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h index 3fd72109..b45b5f1 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.h +++ b/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -360,7 +360,9 @@ // Exposed for tests. aura::Window* window() { return window_; } SkColorType PreferredReadbackFormat() override; - DelegatedFrameHost* GetDelegatedFrameHost() const override; + DelegatedFrameHost* GetDelegatedFrameHost() const { + return delegated_frame_host_.get(); + } const ui::MotionEventAura& pointer_state() const { return pointer_state_; } private: @@ -371,6 +373,7 @@ FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, TouchEventPositionsArentRounded); FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, TouchEventSyncAsync); + FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, Resize); FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, SwapNotifiesWindow); FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, RecreateLayers); FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, @@ -450,14 +453,23 @@ void RemovingFromRootWindow(); // DelegatedFrameHostClient implementation. - ui::Compositor* GetCompositor() const override; - ui::Layer* GetLayer() override; - RenderWidgetHostImpl* GetHost() override; - bool IsVisible() override; - scoped_ptr<ResizeLock> CreateResizeLock(bool defer_compositor_lock) override; - gfx::Size DesiredFrameSize() override; - float CurrentDeviceScaleFactor() override; - gfx::Size ConvertViewSizeToPixel(const gfx::Size& size) override; + ui::Layer* DelegatedFrameHostGetLayer() const override; + bool DelegatedFrameHostIsVisible() const override; + gfx::Size DelegatedFrameHostDesiredSizeInDIP() const override; + bool DelegatedFrameCanCreateResizeLock() const override; + scoped_ptr<ResizeLock> DelegatedFrameHostCreateResizeLock( + bool defer_compositor_lock) override; + void DelegatedFrameHostResizeLockWasReleased() override; + void DelegatedFrameHostSendCompositorSwapAck( + int output_surface_id, + const cc::CompositorFrameAck& ack) override; + void DelegatedFrameHostSendReclaimCompositorResources( + int output_surface_id, + const cc::CompositorFrameAck& ack) override; + void DelegatedFrameHostOnLostCompositorResources() override; + void DelegatedFrameHostUpdateVSyncParameters( + const base::TimeTicks& timebase, + const base::TimeDelta& interval) override; // Detaches |this| from the input method object. void DetachFromInputMethod();
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 b39f5bda..517a59dd 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
@@ -217,22 +217,21 @@ ~FakeRenderWidgetHostViewAura() override {} - scoped_ptr<ResizeLock> CreateResizeLock(bool defer_compositor_lock) override { + scoped_ptr<ResizeLock> DelegatedFrameHostCreateResizeLock( + bool defer_compositor_lock) override { gfx::Size desired_size = window()->bounds().size(); return scoped_ptr<ResizeLock>( new FakeResizeLock(desired_size, defer_compositor_lock)); } + bool DelegatedFrameCanCreateResizeLock() const override { return true; } + void RunOnCompositingDidCommit() { GetDelegatedFrameHost()->OnCompositingDidCommitForTesting( window()->GetHost()->compositor()); } - bool ShouldCreateResizeLock() override { - return GetDelegatedFrameHost()->ShouldCreateResizeLockForTesting(); - } - - void RequestCopyOfOutput(scoped_ptr<cc::CopyOutputRequest> request) override { + void InterceptCopyOfOutput(scoped_ptr<cc::CopyOutputRequest> request) { last_copy_request_ = request.Pass(); if (last_copy_request_->has_texture_mailbox()) { // Give the resulting texture a size. @@ -2042,6 +2041,9 @@ scoped_ptr<cc::CopyOutputRequest> request; view_->InitAsChild(NULL); + view_->GetDelegatedFrameHost()->SetRequestCopyOfOutputCallbackForTesting( + base::Bind(&FakeRenderWidgetHostViewAura::InterceptCopyOfOutput, + base::Unretained(view_))); aura::client::ParentWindowWithContext( view_->GetNativeView(), parent_view_->GetNativeView()->GetRootWindow(),
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.h b/content/browser/renderer_host/render_widget_host_view_mac.h index 0b28e21..57c9369 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac.h +++ b/content/browser/renderer_host/render_widget_host_view_mac.h
@@ -450,15 +450,23 @@ void PauseForPendingResizeOrRepaintsAndDraw(); // DelegatedFrameHostClient implementation. - ui::Compositor* GetCompositor() const override; - ui::Layer* GetLayer() override; - RenderWidgetHostImpl* GetHost() override; - bool IsVisible() override; - scoped_ptr<ResizeLock> CreateResizeLock(bool defer_compositor_lock) override; - gfx::Size DesiredFrameSize() override; - float CurrentDeviceScaleFactor() override; - gfx::Size ConvertViewSizeToPixel(const gfx::Size& size) override; - DelegatedFrameHost* GetDelegatedFrameHost() const override; + ui::Layer* DelegatedFrameHostGetLayer() const override; + bool DelegatedFrameHostIsVisible() const override; + gfx::Size DelegatedFrameHostDesiredSizeInDIP() const override; + bool DelegatedFrameCanCreateResizeLock() const override; + scoped_ptr<ResizeLock> DelegatedFrameHostCreateResizeLock( + bool defer_compositor_lock) override; + void DelegatedFrameHostResizeLockWasReleased() override; + void DelegatedFrameHostSendCompositorSwapAck( + int output_surface_id, + const cc::CompositorFrameAck& ack) override; + void DelegatedFrameHostSendReclaimCompositorResources( + int output_surface_id, + const cc::CompositorFrameAck& ack) override; + void DelegatedFrameHostOnLostCompositorResources() override; + void DelegatedFrameHostUpdateVSyncParameters( + const base::TimeTicks& timebase, + const base::TimeDelta& interval) override; // AcceleratedWidgetMacNSView implementation. NSView* AcceleratedWidgetGetNSView() const override;
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm index 130084f3..de2d049 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac.mm +++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -394,49 +394,56 @@ //////////////////////////////////////////////////////////////////////////////// // DelegatedFrameHost, public: -ui::Compositor* RenderWidgetHostViewMac::GetCompositor() const { - // When |browser_compositor_| is suspended or destroyed, the connection - // between its ui::Compositor and |delegated_frame_host_| has been severed. - if (browser_compositor_state_ == BrowserCompositorActive) - return browser_compositor_->compositor(); - return NULL; -} - -ui::Layer* RenderWidgetHostViewMac::GetLayer() { +ui::Layer* RenderWidgetHostViewMac::DelegatedFrameHostGetLayer() const { return root_layer_.get(); } -RenderWidgetHostImpl* RenderWidgetHostViewMac::GetHost() { - return render_widget_host_; -} - -bool RenderWidgetHostViewMac::IsVisible() { +bool RenderWidgetHostViewMac::DelegatedFrameHostIsVisible() const { return !render_widget_host_->is_hidden(); } -gfx::Size RenderWidgetHostViewMac::DesiredFrameSize() { +gfx::Size RenderWidgetHostViewMac::DelegatedFrameHostDesiredSizeInDIP() const { return GetViewBounds().size(); } -float RenderWidgetHostViewMac::CurrentDeviceScaleFactor() { - return ViewScaleFactor(); +bool RenderWidgetHostViewMac::DelegatedFrameCanCreateResizeLock() const { + // Mac uses the RenderWidgetResizeHelper instead of a resize lock. + return false; } -gfx::Size RenderWidgetHostViewMac::ConvertViewSizeToPixel( - const gfx::Size& size) { - return gfx::ToEnclosingRect(gfx::ScaleRect(gfx::Rect(size), - ViewScaleFactor())).size(); -} - -scoped_ptr<ResizeLock> RenderWidgetHostViewMac::CreateResizeLock( +scoped_ptr<ResizeLock> +RenderWidgetHostViewMac::DelegatedFrameHostCreateResizeLock( bool defer_compositor_lock) { NOTREACHED(); - ResizeLock* lock = NULL; - return scoped_ptr<ResizeLock>(lock); + return scoped_ptr<ResizeLock>(); } -DelegatedFrameHost* RenderWidgetHostViewMac::GetDelegatedFrameHost() const { - return delegated_frame_host_.get(); +void RenderWidgetHostViewMac::DelegatedFrameHostResizeLockWasReleased() { + NOTREACHED(); +} + +void RenderWidgetHostViewMac::DelegatedFrameHostSendCompositorSwapAck( + int output_surface_id, + const cc::CompositorFrameAck& ack) { + render_widget_host_->Send(new ViewMsg_SwapCompositorFrameAck( + render_widget_host_->GetRoutingID(), output_surface_id, ack)); +} + +void RenderWidgetHostViewMac::DelegatedFrameHostSendReclaimCompositorResources( + int output_surface_id, + const cc::CompositorFrameAck& ack) { + render_widget_host_->Send(new ViewMsg_ReclaimCompositorResources( + render_widget_host_->GetRoutingID(), output_surface_id, ack)); +} + +void RenderWidgetHostViewMac::DelegatedFrameHostOnLostCompositorResources() { + render_widget_host_->ScheduleComposite(); +} + +void RenderWidgetHostViewMac::DelegatedFrameHostUpdateVSyncParameters( + const base::TimeTicks& timebase, + const base::TimeDelta& interval) { + render_widget_host_->UpdateVSyncParameters(timebase, interval); } //////////////////////////////////////////////////////////////////////////////// @@ -603,7 +610,7 @@ // Show the DelegatedFrameHost to transition from Suspended -> Active. if (browser_compositor_state_ == BrowserCompositorSuspended) { - delegated_frame_host_->AddedToWindow(); + delegated_frame_host_->SetCompositor(browser_compositor_->compositor()); delegated_frame_host_->WasShown(ui::LatencyInfo()); browser_compositor_->compositor()->SetRootLayer( root_layer_.get()); @@ -623,7 +630,7 @@ // Marking the DelegatedFrameHost as removed from the window hierarchy is // necessary to remove all connections to its old ui::Compositor. delegated_frame_host_->WasHidden(); - delegated_frame_host_->RemovingFromWindow(); + delegated_frame_host_->ResetCompositor(); browser_compositor_state_ = BrowserCompositorSuspended; } } @@ -822,7 +829,6 @@ return render_widget_host_; } - void RenderWidgetHostViewMac::Show() { [cocoa_view_ setHidden:NO]; if (!render_widget_host_->is_hidden()) @@ -2559,7 +2565,8 @@ - (id)accessibilityAttributeValue:(NSString *)attribute { BrowserAccessibilityManager* manager = - renderWidgetHostView_->GetHost()->GetRootBrowserAccessibilityManager(); + renderWidgetHostView_->render_widget_host_ + ->GetRootBrowserAccessibilityManager(); // Contents specifies document view of RenderWidgetHostViewCocoa provided by // BrowserAccessibilityManager. Children includes all subviews in addition to @@ -2585,7 +2592,8 @@ - (id)accessibilityHitTest:(NSPoint)point { BrowserAccessibilityManager* manager = - renderWidgetHostView_->GetHost()->GetRootBrowserAccessibilityManager(); + renderWidgetHostView_->render_widget_host_ + ->GetRootBrowserAccessibilityManager(); if (!manager) return self; NSPoint pointInWindow = [[self window] convertScreenToBase:point]; @@ -2599,13 +2607,15 @@ - (BOOL)accessibilityIsIgnored { BrowserAccessibilityManager* manager = - renderWidgetHostView_->GetHost()->GetRootBrowserAccessibilityManager(); + renderWidgetHostView_->render_widget_host_ + ->GetRootBrowserAccessibilityManager(); return !manager; } - (NSUInteger)accessibilityGetIndexOf:(id)child { BrowserAccessibilityManager* manager = - renderWidgetHostView_->GetHost()->GetRootBrowserAccessibilityManager(); + renderWidgetHostView_->render_widget_host_ + ->GetRootBrowserAccessibilityManager(); // Only child is root. if (manager && manager->GetRoot()->ToBrowserAccessibilityCocoa() == child) { @@ -2617,7 +2627,8 @@ - (id)accessibilityFocusedUIElement { BrowserAccessibilityManager* manager = - renderWidgetHostView_->GetHost()->GetRootBrowserAccessibilityManager(); + renderWidgetHostView_->render_widget_host_ + ->GetRootBrowserAccessibilityManager(); if (manager) { BrowserAccessibility* focused_item = manager->GetFocus(NULL); DCHECK(focused_item);
diff --git a/content/browser/service_worker/service_worker_browsertest.cc b/content/browser/service_worker/service_worker_browsertest.cc index f65a7ee..ec45a26a2 100644 --- a/content/browser/service_worker/service_worker_browsertest.cc +++ b/content/browser/service_worker/service_worker_browsertest.cc
@@ -25,6 +25,7 @@ #include "content/public/browser/storage_partition.h" #include "content/public/browser/web_contents.h" #include "content/public/common/content_switches.h" +#include "content/public/common/referrer.h" #include "content/public/test/browser_test_utils.h" #include "content/public/test/content_browser_test.h" #include "content/public/test/content_browser_test_utils.h" @@ -37,8 +38,8 @@ #include "net/url_request/url_request_interceptor.h" #include "net/url_request/url_request_test_job.h" #include "storage/browser/blob/blob_data_handle.h" +#include "storage/browser/blob/blob_data_snapshot.h" #include "storage/browser/blob/blob_storage_context.h" -#include "storage/common/blob/blob_data.h" namespace content { @@ -124,9 +125,10 @@ void ReadResponseBody(std::string* body, storage::BlobDataHandle* blob_data_handle) { ASSERT_TRUE(blob_data_handle); - ASSERT_EQ(1U, blob_data_handle->data()->items().size()); - *body = std::string(blob_data_handle->data()->items()[0].bytes(), - blob_data_handle->data()->items()[0].length()); + scoped_ptr<storage::BlobDataSnapshot> data = + blob_data_handle->CreateSnapshot(); + ASSERT_EQ(1U, data->items().size()); + *body = std::string(data->items()[0]->bytes(), data->items()[0]->length()); } void ExpectResultAndRun(bool expected, @@ -547,7 +549,7 @@ embedded_test_server()->GetURL("/service_worker/empty.html"), "GET", ServiceWorkerHeaderMap(), - GURL(""), + Referrer(), false); version_->SetStatus(ServiceWorkerVersion::ACTIVATED); version_->DispatchFetchEvent(
diff --git a/content/browser/service_worker/service_worker_cache.cc b/content/browser/service_worker/service_worker_cache.cc index 3011356..ebbcc93 100644 --- a/content/browser/service_worker/service_worker_cache.cc +++ b/content/browser/service_worker/service_worker_cache.cc
@@ -13,10 +13,12 @@ #include "base/strings/string_util.h" #include "content/browser/service_worker/service_worker_cache.pb.h" #include "content/public/browser/browser_thread.h" +#include "content/public/common/referrer.h" #include "net/base/io_buffer.h" #include "net/base/net_errors.h" #include "net/disk_cache/disk_cache.h" #include "net/url_request/url_request_context.h" +#include "storage/browser/blob/blob_data_builder.h" #include "storage/browser/blob/blob_data_handle.h" #include "storage/browser/blob/blob_storage_context.h" #include "storage/browser/blob/blob_url_request_job_factory.h" @@ -343,7 +345,7 @@ // Output scoped_ptr<ServiceWorkerResponse> response; - scoped_refptr<storage::BlobData> blob_data; + scoped_ptr<storage::BlobDataBuilder> blob_data; // For reading the cache entry data into a blob. scoped_refptr<net::IOBufferWithSize> response_body_buffer; @@ -428,29 +430,27 @@ void ServiceWorkerCache::Put(scoped_ptr<ServiceWorkerFetchRequest> request, scoped_ptr<ServiceWorkerResponse> response, const ResponseCallback& callback) { - IncPendingOps(); - ResponseCallback pending_callback = - base::Bind(&ServiceWorkerCache::PendingResponseCallback, - weak_ptr_factory_.GetWeakPtr(), callback); scoped_ptr<storage::BlobDataHandle> blob_data_handle; if (!response->blob_uuid.empty()) { if (!blob_storage_context_) { - pending_callback.Run(ErrorTypeStorage, - scoped_ptr<ServiceWorkerResponse>(), - scoped_ptr<storage::BlobDataHandle>()); + callback.Run(ErrorTypeStorage, scoped_ptr<ServiceWorkerResponse>(), + scoped_ptr<storage::BlobDataHandle>()); return; } blob_data_handle = blob_storage_context_->GetBlobDataFromUUID(response->blob_uuid); if (!blob_data_handle) { - pending_callback.Run(ErrorTypeStorage, - scoped_ptr<ServiceWorkerResponse>(), - scoped_ptr<storage::BlobDataHandle>()); + callback.Run(ErrorTypeStorage, scoped_ptr<ServiceWorkerResponse>(), + scoped_ptr<storage::BlobDataHandle>()); return; } } + ResponseCallback pending_callback = + base::Bind(&ServiceWorkerCache::PendingResponseCallback, + weak_ptr_factory_.GetWeakPtr(), callback); + scoped_ptr<PutContext> put_context(new PutContext( origin_, request.Pass(), response.Pass(), blob_data_handle.Pass(), pending_callback, request_context_, quota_manager_proxy_)); @@ -462,30 +462,30 @@ put_context->response->blob_uuid); } - base::Closure continuation = - base::Bind(&ServiceWorkerCache::PutImpl, weak_ptr_factory_.GetWeakPtr(), - base::Passed(put_context.Pass())); + pending_operations_.push_back(base::Bind(&ServiceWorkerCache::PutImpl, + weak_ptr_factory_.GetWeakPtr(), + base::Passed(put_context.Pass()))); if (backend_state_ == BACKEND_UNINITIALIZED) { - InitBackend(continuation); + InitBackend(); return; } - continuation.Run(); + RunOperationIfIdle(); } void ServiceWorkerCache::Match(scoped_ptr<ServiceWorkerFetchRequest> request, const ResponseCallback& callback) { - IncPendingOps(); ResponseCallback pending_callback = base::Bind(&ServiceWorkerCache::PendingResponseCallback, weak_ptr_factory_.GetWeakPtr(), callback); + pending_operations_.push_back( + base::Bind(&ServiceWorkerCache::MatchImpl, weak_ptr_factory_.GetWeakPtr(), + base::Passed(request.Pass()), pending_callback)); switch (backend_state_) { case BACKEND_UNINITIALIZED: - InitBackend(base::Bind(&ServiceWorkerCache::Match, - weak_ptr_factory_.GetWeakPtr(), - base::Passed(request.Pass()), pending_callback)); + InitBackend(); return; case BACKEND_CLOSED: pending_callback.Run(ErrorTypeStorage, @@ -494,122 +494,71 @@ return; case BACKEND_OPEN: DCHECK(backend_); - break; + RunOperationIfIdle(); + return; } - - scoped_ptr<MatchContext> match_context(new MatchContext( - request.Pass(), pending_callback, blob_storage_context_)); - - disk_cache::Entry** entry_ptr = &match_context->entry; - ServiceWorkerFetchRequest* request_ptr = match_context->request.get(); - - net::CompletionCallback open_entry_callback = base::Bind( - &ServiceWorkerCache::MatchDidOpenEntry, weak_ptr_factory_.GetWeakPtr(), - base::Passed(match_context.Pass())); - - int rv = backend_->OpenEntry( - request_ptr->url.spec(), entry_ptr, open_entry_callback); - if (rv != net::ERR_IO_PENDING) - open_entry_callback.Run(rv); + NOTREACHED(); } void ServiceWorkerCache::Delete(scoped_ptr<ServiceWorkerFetchRequest> request, const ErrorCallback& callback) { - IncPendingOps(); ErrorCallback pending_callback = base::Bind(&ServiceWorkerCache::PendingErrorCallback, weak_ptr_factory_.GetWeakPtr(), callback); + pending_operations_.push_back(base::Bind( + &ServiceWorkerCache::DeleteImpl, weak_ptr_factory_.GetWeakPtr(), + base::Passed(request.Pass()), pending_callback)); switch (backend_state_) { case BACKEND_UNINITIALIZED: - InitBackend(base::Bind(&ServiceWorkerCache::Delete, - weak_ptr_factory_.GetWeakPtr(), - base::Passed(request.Pass()), pending_callback)); + InitBackend(); return; case BACKEND_CLOSED: pending_callback.Run(ErrorTypeStorage); return; case BACKEND_OPEN: DCHECK(backend_); - break; + RunOperationIfIdle(); + return; } - - scoped_ptr<disk_cache::Entry*> entry(new disk_cache::Entry*); - - disk_cache::Entry** entry_ptr = entry.get(); - - ServiceWorkerFetchRequest* request_ptr = request.get(); - - net::CompletionCallback open_entry_callback = base::Bind( - &ServiceWorkerCache::DeleteDidOpenEntry, weak_ptr_factory_.GetWeakPtr(), - origin_, base::Passed(request.Pass()), pending_callback, - base::Passed(entry.Pass()), quota_manager_proxy_); - - int rv = backend_->OpenEntry( - request_ptr->url.spec(), entry_ptr, open_entry_callback); - if (rv != net::ERR_IO_PENDING) - open_entry_callback.Run(rv); + NOTREACHED(); } void ServiceWorkerCache::Keys(const RequestsCallback& callback) { - IncPendingOps(); RequestsCallback pending_callback = base::Bind(&ServiceWorkerCache::PendingRequestsCallback, weak_ptr_factory_.GetWeakPtr(), callback); + pending_operations_.push_back(base::Bind(&ServiceWorkerCache::KeysImpl, + weak_ptr_factory_.GetWeakPtr(), + pending_callback)); switch (backend_state_) { case BACKEND_UNINITIALIZED: - InitBackend(base::Bind(&ServiceWorkerCache::Keys, - weak_ptr_factory_.GetWeakPtr(), pending_callback)); + InitBackend(); return; case BACKEND_CLOSED: pending_callback.Run(ErrorTypeStorage, scoped_ptr<Requests>()); return; case BACKEND_OPEN: DCHECK(backend_); - break; + RunOperationIfIdle(); + return; } - - // 1. Iterate through all of the entries, open them, and add them to a vector. - // 2. For each open entry: - // 2.1. Read the headers into a protobuf. - // 2.2. Copy the protobuf into a ServiceWorkerFetchRequest (a "key"). - // 2.3. Push the response into a vector of requests to be returned. - // 3. Return the vector of requests (keys). - - // The entries have to be loaded into a vector first because enumeration loops - // forever if you read data from a cache entry while enumerating. - - scoped_ptr<KeysContext> keys_context(new KeysContext(pending_callback)); - - keys_context->backend_iterator = backend_->CreateIterator(); - disk_cache::Backend::Iterator& iterator = *keys_context->backend_iterator; - disk_cache::Entry** enumerated_entry = &keys_context->enumerated_entry; - - net::CompletionCallback open_entry_callback = base::Bind( - &ServiceWorkerCache::KeysDidOpenNextEntry, weak_ptr_factory_.GetWeakPtr(), - base::Passed(keys_context.Pass())); - - int rv = iterator.OpenNextEntry(enumerated_entry, open_entry_callback); - - if (rv != net::ERR_IO_PENDING) - open_entry_callback.Run(rv); + NOTREACHED(); } void ServiceWorkerCache::Close(const base::Closure& callback) { DCHECK(backend_state_ != BACKEND_CLOSED) << "Don't call ServiceWorkerCache::Close() twice."; - backend_state_ = BACKEND_CLOSED; - if (pending_ops_ > 0) { - DCHECK(ops_complete_callback_.is_null()); - ops_complete_callback_ = - base::Bind(&ServiceWorkerCache::CloseImpl, - weak_ptr_factory_.GetWeakPtr(), callback); - return; - } + base::Closure pending_callback = + base::Bind(&ServiceWorkerCache::PendingClosure, + weak_ptr_factory_.GetWeakPtr(), callback); - CloseImpl(callback); + pending_operations_.push_back(base::Bind(&ServiceWorkerCache::CloseImpl, + weak_ptr_factory_.GetWeakPtr(), + pending_callback)); + RunOperationIfIdle(); } int64 ServiceWorkerCache::MemoryBackedSize() const { @@ -652,11 +601,38 @@ quota_manager_proxy_(quota_manager_proxy), blob_storage_context_(blob_context), backend_state_(BACKEND_UNINITIALIZED), + operation_running_(false), + initializing_(false), memory_only_(path.empty()), - pending_ops_(0), weak_ptr_factory_(this) { } +void ServiceWorkerCache::MatchImpl( + scoped_ptr<ServiceWorkerFetchRequest> request, + const ResponseCallback& callback) { + DCHECK(backend_state_ != BACKEND_UNINITIALIZED); + if (backend_state_ != BACKEND_OPEN) { + callback.Run(ErrorTypeStorage, scoped_ptr<ServiceWorkerResponse>(), + scoped_ptr<storage::BlobDataHandle>()); + return; + } + + scoped_ptr<MatchContext> match_context( + new MatchContext(request.Pass(), callback, blob_storage_context_)); + + disk_cache::Entry** entry_ptr = &match_context->entry; + ServiceWorkerFetchRequest* request_ptr = match_context->request.get(); + + net::CompletionCallback open_entry_callback = base::Bind( + &ServiceWorkerCache::MatchDidOpenEntry, weak_ptr_factory_.GetWeakPtr(), + base::Passed(match_context.Pass())); + + int rv = backend_->OpenEntry(request_ptr->url.spec(), entry_ptr, + open_entry_callback); + if (rv != net::ERR_IO_PENDING) + open_entry_callback.Run(rv); +} + void ServiceWorkerCache::MatchDidOpenEntry( scoped_ptr<MatchContext> match_context, int rv) { @@ -735,7 +711,8 @@ response->blob_uuid = base::GenerateGUID(); - match_context->blob_data = new storage::BlobData(response->blob_uuid); + match_context->blob_data.reset( + new storage::BlobDataBuilder(response->blob_uuid)); match_context->response_body_buffer = new net::IOBufferWithSize(kBufferSize); disk_cache::Entry* tmp_entry_ptr = match_context->entry; @@ -810,7 +787,7 @@ scoped_ptr<storage::BlobDataHandle> blob_data_handle( match_context->blob_storage_context->AddFinishedBlob( - match_context->blob_data.get())); + *match_context->blob_data.get())); match_context->original_callback.Run(ServiceWorkerCache::ErrorTypeOK, match_context->response.Pass(), @@ -818,6 +795,7 @@ } void ServiceWorkerCache::PutImpl(scoped_ptr<PutContext> put_context) { + DCHECK(backend_state_ != BACKEND_UNINITIALIZED); if (backend_state_ != BACKEND_OPEN) { put_context->callback.Run(ErrorTypeStorage, scoped_ptr<ServiceWorkerResponse>(), @@ -828,9 +806,9 @@ scoped_ptr<ServiceWorkerFetchRequest> request_copy( new ServiceWorkerFetchRequest(*put_context->request)); - Delete(request_copy.Pass(), base::Bind(&ServiceWorkerCache::PutDidDelete, - weak_ptr_factory_.GetWeakPtr(), - base::Passed(put_context.Pass()))); + DeleteImpl(request_copy.Pass(), base::Bind(&ServiceWorkerCache::PutDidDelete, + weak_ptr_factory_.GetWeakPtr(), + base::Passed(put_context.Pass()))); } void ServiceWorkerCache::PutDidDelete(scoped_ptr<PutContext> put_context, @@ -1003,6 +981,31 @@ put_context->out_blob_data_handle.Pass()); } +void ServiceWorkerCache::DeleteImpl( + scoped_ptr<ServiceWorkerFetchRequest> request, + const ErrorCallback& callback) { + DCHECK(backend_state_ != BACKEND_UNINITIALIZED); + if (backend_state_ != BACKEND_OPEN) { + callback.Run(ErrorTypeStorage); + return; + } + scoped_ptr<disk_cache::Entry*> entry(new disk_cache::Entry*); + + disk_cache::Entry** entry_ptr = entry.get(); + + ServiceWorkerFetchRequest* request_ptr = request.get(); + + net::CompletionCallback open_entry_callback = base::Bind( + &ServiceWorkerCache::DeleteDidOpenEntry, weak_ptr_factory_.GetWeakPtr(), + origin_, base::Passed(request.Pass()), callback, + base::Passed(entry.Pass()), quota_manager_proxy_); + + int rv = backend_->OpenEntry(request_ptr->url.spec(), entry_ptr, + open_entry_callback); + if (rv != net::ERR_IO_PENDING) + open_entry_callback.Run(rv); +} + void ServiceWorkerCache::DeleteDidOpenEntry( const GURL& origin, scoped_ptr<ServiceWorkerFetchRequest> request, @@ -1030,6 +1033,39 @@ callback.Run(ServiceWorkerCache::ErrorTypeOK); } +void ServiceWorkerCache::KeysImpl(const RequestsCallback& callback) { + DCHECK(backend_state_ != BACKEND_UNINITIALIZED); + if (backend_state_ != BACKEND_OPEN) { + callback.Run(ErrorTypeStorage, scoped_ptr<Requests>()); + return; + } + + // 1. Iterate through all of the entries, open them, and add them to a vector. + // 2. For each open entry: + // 2.1. Read the headers into a protobuf. + // 2.2. Copy the protobuf into a ServiceWorkerFetchRequest (a "key"). + // 2.3. Push the response into a vector of requests to be returned. + // 3. Return the vector of requests (keys). + + // The entries have to be loaded into a vector first because enumeration loops + // forever if you read data from a cache entry while enumerating. + + scoped_ptr<KeysContext> keys_context(new KeysContext(callback)); + + keys_context->backend_iterator = backend_->CreateIterator(); + disk_cache::Backend::Iterator& iterator = *keys_context->backend_iterator; + disk_cache::Entry** enumerated_entry = &keys_context->enumerated_entry; + + net::CompletionCallback open_entry_callback = base::Bind( + &ServiceWorkerCache::KeysDidOpenNextEntry, weak_ptr_factory_.GetWeakPtr(), + base::Passed(keys_context.Pass())); + + int rv = iterator.OpenNextEntry(enumerated_entry, open_entry_callback); + + if (rv != net::ERR_IO_PENDING) + open_entry_callback.Run(rv); +} + void ServiceWorkerCache::KeysDidOpenNextEntry( scoped_ptr<KeysContext> keys_context, int rv) { @@ -1096,7 +1132,7 @@ ServiceWorkerFetchRequest(GURL(entry->GetKey()), metadata->request().method(), ServiceWorkerHeaderMap(), - GURL(), + Referrer(), false)); ServiceWorkerHeaderMap& req_headers = @@ -1114,7 +1150,9 @@ } void ServiceWorkerCache::CloseImpl(const base::Closure& callback) { - DCHECK(backend_state_ == BACKEND_CLOSED); + DCHECK(backend_state_ != BACKEND_CLOSED); + + backend_state_ = BACKEND_CLOSED; backend_.reset(); callback.Run(); } @@ -1164,44 +1202,61 @@ callback.Run(ServiceWorkerCache::ErrorTypeOK); } -void ServiceWorkerCache::InitBackend(const base::Closure& callback) { +void ServiceWorkerCache::InitBackend() { DCHECK(backend_state_ == BACKEND_UNINITIALIZED); - init_callbacks_.push_back(callback); - // If this isn't the first call to Init then return as the initialization - // has already started. - if (init_callbacks_.size() > 1u) + if (initializing_) { + DCHECK(operation_running_); return; + } - CreateBackend(base::Bind(&ServiceWorkerCache::InitDone, - weak_ptr_factory_.GetWeakPtr())); + DCHECK(!operation_running_); // All ops should wait for backend init. + initializing_ = true; + // Note that this operation pushes to the front of the queue. + pending_operations_.push_front(base::Bind( + &ServiceWorkerCache::CreateBackend, weak_ptr_factory_.GetWeakPtr(), + base::Bind(&ServiceWorkerCache::InitDone, + weak_ptr_factory_.GetWeakPtr()))); + RunOperationIfIdle(); } void ServiceWorkerCache::InitDone(ErrorType error) { + initializing_ = false; backend_state_ = (error == ErrorTypeOK && backend_ && backend_state_ == BACKEND_UNINITIALIZED) ? BACKEND_OPEN : BACKEND_CLOSED; - for (std::vector<base::Closure>::iterator it = init_callbacks_.begin(); - it != init_callbacks_.end(); ++it) { - it->Run(); - } - init_callbacks_.clear(); + CompleteOperationAndRunNext(); } -void ServiceWorkerCache::DecPendingOps() { - DCHECK(pending_ops_ > 0); - pending_ops_--; - if (pending_ops_ == 0 && !ops_complete_callback_.is_null()) { - ops_complete_callback_.Run(); - ops_complete_callback_.Reset(); +void ServiceWorkerCache::CompleteOperationAndRunNext() { + DCHECK(!pending_operations_.empty()); + operation_running_ = false; + pending_operations_.pop_front(); + RunOperationIfIdle(); +} + +void ServiceWorkerCache::RunOperationIfIdle() { + DCHECK(!operation_running_ || !pending_operations_.empty()); + + if (!operation_running_ && !pending_operations_.empty()) { + operation_running_ = true; + // TODO(jkarlin): Run multiple operations in parallel where allowed (e.g., + // if they're for different keys then they won't interfere). See + // https://crbug.com/451174. + pending_operations_.front().Run(); } } +void ServiceWorkerCache::PendingClosure(const base::Closure& callback) { + callback.Run(); + CompleteOperationAndRunNext(); +} + void ServiceWorkerCache::PendingErrorCallback(const ErrorCallback& callback, ErrorType error) { callback.Run(error); - DecPendingOps(); + CompleteOperationAndRunNext(); } void ServiceWorkerCache::PendingResponseCallback( @@ -1210,7 +1265,7 @@ scoped_ptr<ServiceWorkerResponse> response, scoped_ptr<storage::BlobDataHandle> blob_data_handle) { callback.Run(error, response.Pass(), blob_data_handle.Pass()); - DecPendingOps(); + CompleteOperationAndRunNext(); } void ServiceWorkerCache::PendingRequestsCallback( @@ -1218,7 +1273,7 @@ ErrorType error, scoped_ptr<Requests> requests) { callback.Run(error, requests.Pass()); - DecPendingOps(); + CompleteOperationAndRunNext(); } } // namespace content
diff --git a/content/browser/service_worker/service_worker_cache.h b/content/browser/service_worker/service_worker_cache.h index 15da159..84e4b6d 100644 --- a/content/browser/service_worker/service_worker_cache.h +++ b/content/browser/service_worker/service_worker_cache.h
@@ -5,6 +5,8 @@ #ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CACHE_H_ #define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CACHE_H_ +#include <list> + #include "base/callback.h" #include "base/files/file_path.h" #include "base/memory/ref_counted.h" @@ -19,7 +21,7 @@ } namespace storage { -class BlobData; +class BlobDataBuilder; class BlobDataHandle; class BlobStorageContext; class QuotaManagerProxy; @@ -32,8 +34,8 @@ // Represents a ServiceWorker Cache as seen in // https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html. -// Callbacks to the public functions will be called so long as the cache object -// lives. +// The asynchronous methods are executed serially. Callbacks to the +// public functions will be called so long as the cache object lives. class CONTENT_EXPORT ServiceWorkerCache : public base::RefCounted<ServiceWorkerCache> { public: @@ -86,7 +88,7 @@ // Returns ErrorTypeOK and a vector of requests if there are no errors. void Keys(const RequestsCallback& callback); - // Closes the backend. Pending and future operations that require the backend + // Closes the backend. Future operations that require the backend // will exit early. Close should only be called once per ServiceWorkerCache. void Close(const base::Closure& callback); @@ -127,6 +129,8 @@ virtual ~ServiceWorkerCache(); // Match callbacks + void MatchImpl(scoped_ptr<ServiceWorkerFetchRequest> request, + const ResponseCallback& callback); void MatchDidOpenEntry(scoped_ptr<MatchContext> match_context, int rv); void MatchDidReadMetadata(scoped_ptr<MatchContext> match_context, scoped_ptr<ServiceWorkerCacheMetadata> headers); @@ -147,6 +151,8 @@ bool success); // Delete callbacks + void DeleteImpl(scoped_ptr<ServiceWorkerFetchRequest> request, + const ErrorCallback& callback); void DeleteDidOpenEntry( const GURL& origin, scoped_ptr<ServiceWorkerFetchRequest> request, @@ -156,6 +162,7 @@ int rv); // Keys callbacks. + void KeysImpl(const RequestsCallback& callback); void KeysDidOpenNextEntry(scoped_ptr<KeysContext> keys_context, int rv); void KeysProcessNextEntry(scoped_ptr<KeysContext> keys_context, const Entries::iterator& iter); @@ -172,11 +179,12 @@ scoped_ptr<ScopedBackendPtr> backend_ptr, int rv); - void InitBackend(const base::Closure& callback); + void InitBackend(); void InitDone(ErrorType error); - void IncPendingOps() { pending_ops_++; } - void DecPendingOps(); + void CompleteOperationAndRunNext(); + void RunOperationIfIdle(); + void PendingClosure(const base::Closure& callback); void PendingErrorCallback(const ErrorCallback& callback, ErrorType error); void PendingResponseCallback( const ResponseCallback& callback, @@ -187,28 +195,22 @@ ErrorType error, scoped_ptr<Requests> requests); - // The backend can be deleted via the Close function at any time so always - // check for its existence before use. + // Be sure to check |backend_state_| before use. scoped_ptr<disk_cache::Backend> backend_; + GURL origin_; base::FilePath path_; net::URLRequestContext* request_context_; scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy_; base::WeakPtr<storage::BlobStorageContext> blob_storage_context_; BackendState backend_state_; - std::vector<base::Closure> init_callbacks_; + std::list<base::Closure> pending_operations_; + bool operation_running_; + bool initializing_; // Whether or not to store data in disk or memory. bool memory_only_; - // The number of started operations that have yet to complete. - // TODO(jkarlin): pending_ops_ gets double counted on lazy initialization (say - // in ::Put). The counting still works but pending_ops_ doesn't accurately - // represent the number of operations in flight. Fix this by having the lazy - // init callback call a different function than the original caller (::Put). - size_t pending_ops_; - base::Closure ops_complete_callback_; - base::WeakPtrFactory<ServiceWorkerCache> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(ServiceWorkerCache);
diff --git a/content/browser/service_worker/service_worker_cache_unittest.cc b/content/browser/service_worker/service_worker_cache_unittest.cc index e7dbb07..9a8e036 100644 --- a/content/browser/service_worker/service_worker_cache_unittest.cc +++ b/content/browser/service_worker/service_worker_cache_unittest.cc
@@ -13,16 +13,18 @@ #include "content/browser/quota/mock_quota_manager_proxy.h" #include "content/common/service_worker/service_worker_types.h" #include "content/public/browser/browser_thread.h" +#include "content/public/common/referrer.h" #include "content/public/test/test_browser_context.h" #include "content/public/test/test_browser_thread_bundle.h" #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_context_getter.h" #include "net/url_request/url_request_job_factory_impl.h" +#include "storage/browser/blob/blob_data_builder.h" #include "storage/browser/blob/blob_data_handle.h" +#include "storage/browser/blob/blob_data_snapshot.h" #include "storage/browser/blob/blob_storage_context.h" #include "storage/browser/blob/blob_url_request_job_factory.h" #include "storage/browser/quota/quota_manager_proxy.h" -#include "storage/common/blob/blob_data.h" #include "testing/gtest/include/gtest/gtest.h" namespace content { @@ -214,25 +216,26 @@ ServiceWorkerHeaderMap headers; headers.insert(std::make_pair("a", "a")); headers.insert(std::make_pair("b", "b")); - body_request_ = ServiceWorkerFetchRequest( - GURL("http://example.com/body.html"), "GET", headers, GURL(), false); + body_request_ = + ServiceWorkerFetchRequest(GURL("http://example.com/body.html"), "GET", + headers, Referrer(), false); no_body_request_ = ServiceWorkerFetchRequest(GURL("http://example.com/no_body.html"), "GET", headers, - GURL(), + Referrer(), false); std::string expected_response; for (int i = 0; i < 100; ++i) expected_blob_data_ += kTestData; - scoped_refptr<storage::BlobData> blob_data( - new storage::BlobData("blob-id:myblob")); + scoped_ptr<storage::BlobDataBuilder> blob_data( + new storage::BlobDataBuilder("blob-id:myblob")); blob_data->AppendData(expected_blob_data_); blob_handle_ = - blob_storage_context->context()->AddFinishedBlob(blob_data.get()); + blob_storage_context->context()->AddFinishedBlob(*blob_data.get()); body_response_ = ServiceWorkerResponse(GURL("http://example.com/body.html"), @@ -385,10 +388,11 @@ } void CopyBody(storage::BlobDataHandle* blob_handle, std::string* output) { - storage::BlobData* data = blob_handle->data(); - std::vector<storage::BlobData::Item> items = data->items(); - for (size_t i = 0, max = items.size(); i < max; ++i) - output->append(items[i].bytes(), items[i].length()); + scoped_ptr<storage::BlobDataSnapshot> data = blob_handle->CreateSnapshot(); + const auto& items = data->items(); + for (const auto& item : items) { + output->append(item->bytes(), item->length()); + } } bool VerifyKeys(const std::vector<std::string>& expected_keys) { @@ -719,7 +723,7 @@ ServiceWorkerFetchRequest request(GURL("http://www.example.com"), "GET", ServiceWorkerHeaderMap(), - GURL(), + Referrer(), false); request.headers["content-type"] = "foo"; request.headers["Content-Type"] = "bar"; @@ -786,126 +790,43 @@ VerifyAllOpsFail(); } -TEST_P(ServiceWorkerCacheTestP, ClosedDuringPutInitBackend) { - // Even though Close is called in the middle of a Put operation (during - // backend creation), the put operation should exit early. - cache_->set_delay_backend_creation(true); - scoped_ptr<base::RunLoop> close_loop(new base::RunLoop()); - cache_->Put(CopyFetchRequest(body_request_), - CopyFetchResponse(body_response_), - base::Bind(&ServiceWorkerCacheTest::ResponseAndErrorCallback, - base::Unretained(this), nullptr)); - cache_->Close(base::Bind(&ServiceWorkerCacheTest::CloseCallback, - base::Unretained(this), close_loop.get())); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(ServiceWorkerCache::ErrorTypeOK, callback_error_); - EXPECT_FALSE(callback_closed_); - - cache_->ContinueCreateBackend(); - - close_loop->Run(); - EXPECT_EQ(ServiceWorkerCache::ErrorTypeStorage, callback_error_); - EXPECT_TRUE(callback_closed_); - - VerifyAllOpsFail(); -} - -TEST_P(ServiceWorkerCacheTestP, ClosedDuringMatchInitBackend) { - // Even though Close is called in the middle of a Match operation (during - // backend creation), the match operation should exit early. - cache_->set_delay_backend_creation(true); - scoped_ptr<base::RunLoop> close_loop(new base::RunLoop()); - cache_->Match(CopyFetchRequest(body_request_), - base::Bind(&ServiceWorkerCacheTest::ResponseAndErrorCallback, - base::Unretained(this), nullptr)); - cache_->Close(base::Bind(&ServiceWorkerCacheTest::CloseCallback, - base::Unretained(this), close_loop.get())); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(ServiceWorkerCache::ErrorTypeOK, callback_error_); - EXPECT_FALSE(callback_closed_); - - cache_->ContinueCreateBackend(); - - close_loop->Run(); - EXPECT_EQ(ServiceWorkerCache::ErrorTypeStorage, callback_error_); - EXPECT_TRUE(callback_closed_); - - VerifyAllOpsFail(); -} - -TEST_P(ServiceWorkerCacheTestP, ClosedDuringDeleteInitBackend) { - // Even though Close is called in the middle of a Delete operation (during - // backend creation), the delete operation should exit early. - cache_->set_delay_backend_creation(true); - scoped_ptr<base::RunLoop> close_loop(new base::RunLoop()); - cache_->Delete(CopyFetchRequest(body_request_), - base::Bind(&ServiceWorkerCacheTest::ErrorTypeCallback, - base::Unretained(this), nullptr)); - cache_->Close(base::Bind(&ServiceWorkerCacheTest::CloseCallback, - base::Unretained(this), close_loop.get())); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(ServiceWorkerCache::ErrorTypeOK, callback_error_); - EXPECT_FALSE(callback_closed_); - - cache_->ContinueCreateBackend(); - - close_loop->Run(); - EXPECT_EQ(ServiceWorkerCache::ErrorTypeStorage, callback_error_); - EXPECT_TRUE(callback_closed_); - - VerifyAllOpsFail(); -} - -TEST_P(ServiceWorkerCacheTestP, ClosedDuringKeysInitBackend) { - // Even though Close is called in the middle of a Keys operation (during - // backend creation), the keys operation should exit early. - cache_->set_delay_backend_creation(true); - scoped_ptr<base::RunLoop> close_loop(new base::RunLoop()); - cache_->Keys(base::Bind(&ServiceWorkerCacheTest::RequestsCallback, - base::Unretained(this), nullptr)); - cache_->Close(base::Bind(&ServiceWorkerCacheTest::CloseCallback, - base::Unretained(this), close_loop.get())); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(ServiceWorkerCache::ErrorTypeOK, callback_error_); - EXPECT_FALSE(callback_closed_); - - cache_->ContinueCreateBackend(); - - close_loop->Run(); - EXPECT_EQ(ServiceWorkerCache::ErrorTypeStorage, callback_error_); - EXPECT_TRUE(callback_closed_); - - VerifyAllOpsFail(); -} - -TEST_P(ServiceWorkerCacheTestP, ClosedDuringPutOpenEntry) { +TEST_P(ServiceWorkerCacheTestP, VerifySerialScheduling) { + // Start two operations, the first one is delayed but the second isn't. The + // second should wait for the first. EXPECT_TRUE(Keys()); // Opens the backend. DelayableBackend* delayable_backend = cache_->UseDelayableBackend(); delayable_backend->set_delay_open(true); - // Run Put and Close. Put will delay on OpenEntry, Close will wait for Put to - // finish. - scoped_ptr<base::RunLoop> close_loop(new base::RunLoop()); - cache_->Put(CopyFetchRequest(body_request_), - CopyFetchResponse(body_response_), - base::Bind(&ServiceWorkerCacheTest::ResponseAndErrorCallback, - base::Unretained(this), nullptr)); - cache_->Close(base::Bind(&ServiceWorkerCacheTest::CloseCallback, - base::Unretained(this), close_loop.get())); + scoped_ptr<ServiceWorkerResponse> response1 = + CopyFetchResponse(body_response_); + response1->status_code = 1; + scoped_ptr<base::RunLoop> close_loop1(new base::RunLoop()); + cache_->Put(CopyFetchRequest(body_request_), response1.Pass(), + base::Bind(&ServiceWorkerCacheTest::ResponseAndErrorCallback, + base::Unretained(this), close_loop1.get())); + + // Blocks on opening the cache entry. base::RunLoop().RunUntilIdle(); - // Verify that neither operation has finished. - EXPECT_EQ(ServiceWorkerCache::ErrorTypeOK, callback_error_); - EXPECT_FALSE(callback_closed_); + + delayable_backend->set_delay_open(false); + scoped_ptr<ServiceWorkerResponse> response2 = + CopyFetchResponse(body_response_); + response2->status_code = 2; + scoped_ptr<base::RunLoop> close_loop2(new base::RunLoop()); + cache_->Put(CopyFetchRequest(body_request_), response2.Pass(), + base::Bind(&ServiceWorkerCacheTest::ResponseAndErrorCallback, + base::Unretained(this), close_loop2.get())); + + // The second put operation should wait for the first to complete. + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(callback_response_); delayable_backend->OpenEntryContinue(); - - close_loop->Run(); - // Put failed because the backend was closed while it was running. - EXPECT_EQ(ServiceWorkerCache::ErrorTypeStorage, callback_error_); - EXPECT_TRUE(callback_closed_); - - VerifyAllOpsFail(); + close_loop1->Run(); + EXPECT_EQ(1, callback_response_->status_code); + close_loop2->Run(); + EXPECT_EQ(2, callback_response_->status_code); } INSTANTIATE_TEST_CASE_P(ServiceWorkerCacheTest,
diff --git a/content/browser/service_worker/service_worker_dispatcher_host.cc b/content/browser/service_worker/service_worker_dispatcher_host.cc index a8b77c3..20615b6 100644 --- a/content/browser/service_worker/service_worker_dispatcher_host.cc +++ b/content/browser/service_worker/service_worker_dispatcher_host.cc
@@ -552,6 +552,22 @@ return; if (!provider_host->SetHostedVersionId(version_id)) BadMessageReceived(); + + // Retrieve the registration associated with |version_id|. + ServiceWorkerVersion* version = GetContext()->GetLiveVersion(version_id); + if (!version) + return; + ServiceWorkerRegistration* registration = + GetContext()->GetLiveRegistration(version->registration_id()); + DCHECK(registration); + + ServiceWorkerRegistrationObjectInfo info; + ServiceWorkerVersionAttributes attrs; + GetRegistrationObjectInfoAndVersionAttributes( + provider_host->AsWeakPtr(), registration, &info, &attrs); + + Send(new ServiceWorkerMsg_AssociateRegistrationWithServiceWorker( + kDocumentMainThreadId, provider_id, info, attrs)); } ServiceWorkerRegistrationHandle*
diff --git a/content/browser/service_worker/service_worker_url_request_job.cc b/content/browser/service_worker/service_worker_url_request_job.cc index b2d836b..ecac9528 100644 --- a/content/browser/service_worker/service_worker_url_request_job.cc +++ b/content/browser/service_worker/service_worker_url_request_job.cc
@@ -10,6 +10,7 @@ #include "base/bind.h" #include "base/guid.h" +#include "base/memory/scoped_vector.h" #include "base/profiler/scoped_tracker.h" #include "base/strings/stringprintf.h" #include "base/time/time.h" @@ -24,11 +25,13 @@ #include "content/public/browser/blob_handle.h" #include "content/public/browser/resource_request_info.h" #include "content/public/browser/service_worker_context.h" +#include "content/public/common/referrer.h" #include "net/base/net_errors.h" #include "net/http/http_request_headers.h" #include "net/http/http_response_headers.h" #include "net/http/http_response_info.h" #include "net/http/http_util.h" +#include "storage/browser/blob/blob_data_builder.h" #include "storage/browser/blob/blob_data_handle.h" #include "storage/browser/blob/blob_storage_context.h" #include "storage/browser/blob/blob_url_request_job_factory.h" @@ -394,12 +397,19 @@ } request->blob_uuid = blob_uuid; request->blob_size = blob_size; - request->referrer = GURL(request_->referrer()); request->credentials_mode = credentials_mode_; const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request_); if (info) { request->is_reload = ui::PageTransitionCoreTypeIs( info->GetPageTransition(), ui::PAGE_TRANSITION_RELOAD); + request->referrer = + Referrer(GURL(request_->referrer()), info->GetReferrerPolicy()); + } else { + CHECK( + request_->referrer_policy() == + net::URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE); + request->referrer = + Referrer(GURL(request_->referrer()), blink::WebReferrerPolicyDefault); } return request.Pass(); } @@ -409,27 +419,35 @@ if (!body_.get() || !blob_storage_context_) return false; + // To ensure the blobs stick around until the end of the reading. + ScopedVector<storage::BlobDataHandle> handles; + ScopedVector<storage::BlobDataSnapshot> snapshots; + // TODO(dmurph): Allow blobs to be added below, so that the context can + // efficiently re-use blob items for the new blob. std::vector<const ResourceRequestBody::Element*> resolved_elements; - for (size_t i = 0; i < body_->elements()->size(); ++i) { - const ResourceRequestBody::Element& element = (*body_->elements())[i]; + for (const ResourceRequestBody::Element& element : (*body_->elements())) { if (element.type() != ResourceRequestBody::Element::TYPE_BLOB) { resolved_elements.push_back(&element); continue; } scoped_ptr<storage::BlobDataHandle> handle = blob_storage_context_->GetBlobDataFromUUID(element.blob_uuid()); - if (handle->data()->items().empty()) + scoped_ptr<storage::BlobDataSnapshot> snapshot = handle->CreateSnapshot(); + if (snapshot->items().empty()) continue; - for (size_t i = 0; i < handle->data()->items().size(); ++i) { - const storage::BlobData::Item& item = handle->data()->items().at(i); - DCHECK_NE(storage::BlobData::Item::TYPE_BLOB, item.type()); - resolved_elements.push_back(&item); + const auto& items = snapshot->items(); + for (const auto& item : items) { + DCHECK_NE(storage::DataElement::TYPE_BLOB, item->type()); + resolved_elements.push_back(item->data_element_ptr()); } + handles.push_back(handle.release()); + snapshots.push_back(snapshot.release()); } const std::string uuid(base::GenerateGUID()); uint64 total_size = 0; - scoped_refptr<storage::BlobData> blob_data = new storage::BlobData(uuid); + + storage::BlobDataBuilder blob_builder(uuid); for (size_t i = 0; i < resolved_elements.size(); ++i) { const ResourceRequestBody::Element& element = *resolved_elements[i]; if (total_size != kuint64max && element.length() != kuint64max) @@ -438,23 +456,21 @@ total_size = kuint64max; switch (element.type()) { case ResourceRequestBody::Element::TYPE_BYTES: - blob_data->AppendData(element.bytes(), element.length()); + blob_builder.AppendData(element.bytes(), element.length()); break; case ResourceRequestBody::Element::TYPE_FILE: - blob_data->AppendFile(element.path(), - element.offset(), - element.length(), - element.expected_modification_time()); + blob_builder.AppendFile(element.path(), element.offset(), + element.length(), + element.expected_modification_time()); break; case ResourceRequestBody::Element::TYPE_BLOB: // Blob elements should be resolved beforehand. NOTREACHED(); break; case ResourceRequestBody::Element::TYPE_FILE_FILESYSTEM: - blob_data->AppendFileSystemFile(element.filesystem_url(), - element.offset(), - element.length(), - element.expected_modification_time()); + blob_builder.AppendFileSystemFile(element.filesystem_url(), + element.offset(), element.length(), + element.expected_modification_time()); break; default: NOTIMPLEMENTED(); @@ -462,7 +478,7 @@ } request_body_blob_data_handle_ = - blob_storage_context_->AddFinishedBlob(blob_data.get()); + blob_storage_context_->AddFinishedBlob(blob_builder); *blob_uuid = uuid; *blob_size = total_size; return true;
diff --git a/content/browser/service_worker/service_worker_url_request_job_unittest.cc b/content/browser/service_worker/service_worker_url_request_job_unittest.cc index 4199dd9c..28986de 100644 --- a/content/browser/service_worker/service_worker_url_request_job_unittest.cc +++ b/content/browser/service_worker/service_worker_url_request_job_unittest.cc
@@ -36,10 +36,10 @@ #include "net/url_request/url_request.h" #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_job_factory_impl.h" +#include "storage/browser/blob/blob_data_builder.h" #include "storage/browser/blob/blob_storage_context.h" #include "storage/browser/blob/blob_url_request_job.h" #include "storage/browser/blob/blob_url_request_job_factory.h" -#include "storage/common/blob/blob_data.h" #include "testing/gtest/include/gtest/gtest.h" namespace content { @@ -104,7 +104,7 @@ protected: ServiceWorkerURLRequestJobTest() : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP), - blob_data_(new storage::BlobData("blob-id:myblob")) {} + blob_data_(new storage::BlobDataBuilder("blob-id:myblob")) {} ~ServiceWorkerURLRequestJobTest() override {} void SetUp() override { @@ -198,7 +198,7 @@ MockURLRequestDelegate url_request_delegate_; scoped_ptr<net::URLRequest> request_; - scoped_refptr<storage::BlobData> blob_data_; + scoped_ptr<storage::BlobDataBuilder> blob_data_; private: DISALLOW_COPY_AND_ASSIGN(ServiceWorkerURLRequestJobTest); @@ -255,7 +255,7 @@ expected_response += kTestData; } scoped_ptr<storage::BlobDataHandle> blob_handle = - blob_storage_context->context()->AddFinishedBlob(blob_data_.get()); + blob_storage_context->context()->AddFinishedBlob(*blob_data_.get()); SetUpWithHelper(new BlobResponder( kProcessID, blob_handle->uuid(), expected_response.size()));
diff --git a/content/browser/service_worker/service_worker_version.cc b/content/browser/service_worker/service_worker_version.cc index 09cd6f3e..94dce9a 100644 --- a/content/browser/service_worker/service_worker_version.cc +++ b/content/browser/service_worker/service_worker_version.cc
@@ -544,7 +544,7 @@ void ServiceWorkerVersion::DispatchCrossOriginConnectEvent( const CrossOriginConnectCallback& callback, - const CrossOriginServiceWorkerClient& client) { + const NavigatorConnectClient& client) { DCHECK_EQ(ACTIVATED, status()) << status(); if (!base::CommandLine::ForCurrentProcess()->HasSwitch( @@ -574,7 +574,7 @@ } void ServiceWorkerVersion::DispatchCrossOriginMessageEvent( - const CrossOriginServiceWorkerClient& client, + const NavigatorConnectClient& client, const base::string16& message, const std::vector<int>& sent_message_port_ids, const StatusCallback& callback) {
diff --git a/content/browser/service_worker/service_worker_version.h b/content/browser/service_worker/service_worker_version.h index 136cee9..6954a420 100644 --- a/content/browser/service_worker/service_worker_version.h +++ b/content/browser/service_worker/service_worker_version.h
@@ -35,8 +35,8 @@ namespace content { -struct CrossOriginServiceWorkerClient; class EmbeddedWorkerRegistry; +struct NavigatorConnectClient; struct PlatformNotificationData; class ServiceWorkerContextCore; class ServiceWorkerProviderHost; @@ -243,7 +243,7 @@ // This must be called when the status() is ACTIVATED. void DispatchCrossOriginConnectEvent( const CrossOriginConnectCallback& callback, - const CrossOriginServiceWorkerClient& client); + const NavigatorConnectClient& client); // Sends a cross origin message event to the associated embedded worker and // asynchronously calls |callback| when the message was sent (or failed to @@ -254,7 +254,7 @@ // // This must be called when the status() is ACTIVATED. void DispatchCrossOriginMessageEvent( - const CrossOriginServiceWorkerClient& client, + const NavigatorConnectClient& client, const base::string16& message, const std::vector<int>& sent_message_port_ids, const StatusCallback& callback);
diff --git a/content/common/shareable_file_reference_unittest.cc b/content/browser/shareable_file_reference_unittest.cc similarity index 94% rename from content/common/shareable_file_reference_unittest.cc rename to content/browser/shareable_file_reference_unittest.cc index 5e697b9..84d035f 100644 --- a/content/common/shareable_file_reference_unittest.cc +++ b/content/browser/shareable_file_reference_unittest.cc
@@ -1,8 +1,8 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. +// Copyright 2015 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 "storage/common/blob/shareable_file_reference.h" +#include "storage/browser/blob/shareable_file_reference.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h"
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc index e6a5561..4bce3ab 100644 --- a/content/browser/storage_partition_impl.cc +++ b/content/browser/storage_partition_impl.cc
@@ -11,7 +11,8 @@ #include "content/browser/geofencing/geofencing_manager.h" #include "content/browser/gpu/shader_disk_cache.h" #include "content/browser/host_zoom_map_impl.h" -#include "content/browser/navigator_connect/navigator_connect_context.h" +#include "content/browser/navigator_connect/navigator_connect_context_impl.h" +#include "content/browser/navigator_connect/navigator_connect_service_worker_service_factory.h" #include "content/common/dom_storage/dom_storage_types.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" @@ -373,7 +374,7 @@ storage::SpecialStoragePolicy* special_storage_policy, GeofencingManager* geofencing_manager, HostZoomLevelContext* host_zoom_level_context, - NavigatorConnectContext* navigator_connect_context) + NavigatorConnectContextImpl* navigator_connect_context) : partition_path_(partition_path), quota_manager_(quota_manager), appcache_service_(appcache_service), @@ -490,8 +491,10 @@ new HostZoomLevelContext( context->CreateZoomLevelDelegate(partition_path))); - scoped_refptr<NavigatorConnectContext> navigator_connect_context = - new NavigatorConnectContext(service_worker_context); + scoped_refptr<NavigatorConnectContextImpl> navigator_connect_context = + new NavigatorConnectContextImpl(); + navigator_connect_context->AddFactory(make_scoped_ptr( + new NavigatorConnectServiceWorkerServiceFactory(service_worker_context))); StoragePartitionImpl* storage_partition = new StoragePartitionImpl( context, partition_path, quota_manager.get(), appcache_service.get(), @@ -565,7 +568,8 @@ return host_zoom_level_context_->GetZoomLevelDelegate(); } -NavigatorConnectContext* StoragePartitionImpl::GetNavigatorConnectContext() { +NavigatorConnectContextImpl* +StoragePartitionImpl::GetNavigatorConnectContext() { return navigator_connect_context_.get(); }
diff --git a/content/browser/storage_partition_impl.h b/content/browser/storage_partition_impl.h index d9e8ae5bd..8f002766 100644 --- a/content/browser/storage_partition_impl.h +++ b/content/browser/storage_partition_impl.h
@@ -13,6 +13,7 @@ #include "content/browser/host_zoom_level_context.h" #include "content/browser/indexed_db/indexed_db_context_impl.h" #include "content/browser/media/webrtc_identity_store.h" +#include "content/browser/navigator_connect/navigator_connect_context_impl.h" #include "content/browser/service_worker/service_worker_context_wrapper.h" #include "content/common/content_export.h" #include "content/public/browser/storage_partition.h" @@ -48,7 +49,7 @@ HostZoomMap* GetHostZoomMap() override; HostZoomLevelContext* GetHostZoomLevelContext() override; ZoomLevelDelegate* GetZoomLevelDelegate() override; - NavigatorConnectContext* GetNavigatorConnectContext() override; + NavigatorConnectContextImpl* GetNavigatorConnectContext() override; void ClearDataForOrigin(uint32 remove_mask, uint32 quota_storage_remove_mask, @@ -129,7 +130,7 @@ storage::SpecialStoragePolicy* special_storage_policy, GeofencingManager* geofencing_manager, HostZoomLevelContext* host_zoom_level_context, - NavigatorConnectContext* navigator_connect_context); + NavigatorConnectContextImpl* navigator_connect_context); void ClearDataImpl(uint32 remove_mask, uint32 quota_storage_remove_mask, @@ -171,7 +172,7 @@ scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy_; scoped_refptr<GeofencingManager> geofencing_manager_; scoped_refptr<HostZoomLevelContext> host_zoom_level_context_; - scoped_refptr<NavigatorConnectContext> navigator_connect_context_; + scoped_refptr<NavigatorConnectContextImpl> navigator_connect_context_; // Raw pointer that should always be valid. The BrowserContext owns the // StoragePartitionImplMap which then owns StoragePartitionImpl. When the
diff --git a/content/browser/storage_partition_impl_map.cc b/content/browser/storage_partition_impl_map.cc index d8b2e127..00fb52fa 100644 --- a/content/browser/storage_partition_impl_map.cc +++ b/content/browser/storage_partition_impl_map.cc
@@ -30,6 +30,8 @@ #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/content_browser_client.h" +#include "content/public/browser/navigator_connect_context.h" +#include "content/public/browser/navigator_connect_service_factory.h" #include "content/public/browser/storage_partition.h" #include "content/public/common/content_constants.h" #include "content/public/common/url_constants.h" @@ -39,7 +41,6 @@ #include "storage/browser/blob/blob_storage_context.h" #include "storage/browser/blob/blob_url_request_job_factory.h" #include "storage/browser/fileapi/file_system_url_request_job_factory.h" -#include "storage/common/blob/blob_data.h" using storage::FileSystemContext; using storage::BlobStorageContext; @@ -461,6 +462,9 @@ browser_context_->GetMediaRequestContextForStoragePartition( partition->GetPath(), in_memory)); + GetContentClient()->browser()->GetAdditionalNavigatorConnectServices( + partition->GetNavigatorConnectContext()); + PostCreateInitialization(partition, in_memory); return partition;
diff --git a/content/browser/time_zone_monitor_chromeos.cc b/content/browser/time_zone_monitor_chromeos.cc index 8c6aa0b..7ad81789 100644 --- a/content/browser/time_zone_monitor_chromeos.cc +++ b/content/browser/time_zone_monitor_chromeos.cc
@@ -16,12 +16,12 @@ chromeos::system::TimezoneSettings::GetInstance()->AddObserver(this); } - virtual ~TimeZoneMonitorChromeOS() { + ~TimeZoneMonitorChromeOS() override { chromeos::system::TimezoneSettings::GetInstance()->RemoveObserver(this); } // chromeos::system::TimezoneSettings::Observer implementation. - virtual void TimezoneChanged(const icu::TimeZone& time_zone) override { + void TimezoneChanged(const icu::TimeZone& time_zone) override { NotifyRenderers(); }
diff --git a/content/browser/utility_process_host_impl.cc b/content/browser/utility_process_host_impl.cc index 0d24e3a..6f6eb37 100644 --- a/content/browser/utility_process_host_impl.cc +++ b/content/browser/utility_process_host_impl.cc
@@ -194,7 +194,6 @@ *base::CommandLine::ForCurrentProcess(); int child_flags = child_flags_; -#if defined(OS_POSIX) bool has_cmd_prefix = browser_command_line.HasSwitch( switches::kUtilityCmdPrefix); @@ -205,7 +204,6 @@ // a similar case with Valgrind. if (has_cmd_prefix) child_flags = ChildProcessHost::CHILD_NORMAL; -#endif base::FilePath exe_path = ChildProcessHost::GetChildPath(child_flags); if (exe_path.empty()) { @@ -229,7 +227,6 @@ if (browser_command_line.HasSwitch(switches::kDebugPluginLoading)) cmd_line->AppendSwitch(switches::kDebugPluginLoading); -#if defined(OS_POSIX) if (has_cmd_prefix) { // Launch the utility child process with some prefix // (usually "xterm -e gdb --args"). @@ -241,7 +238,6 @@ cmd_line->AppendSwitchPath(switches::kUtilityProcessAllowedDir, exposed_dir_); } -#endif if (is_mdns_enabled_) cmd_line->AppendSwitch(switches::kUtilityProcessEnableMDns);
diff --git a/content/browser/web_contents/touch_editable_impl_aura_browsertest.cc b/content/browser/web_contents/touch_editable_impl_aura_browsertest.cc index d873bfc..77b7318b 100644 --- a/content/browser/web_contents/touch_editable_impl_aura_browsertest.cc +++ b/content/browser/web_contents/touch_editable_impl_aura_browsertest.cc
@@ -98,7 +98,7 @@ } protected: - virtual ~TestTouchEditableImplAura() {} + ~TestTouchEditableImplAura() override {} private: bool selection_changed_callback_arrived_;
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index e910b978..eb9eb5c 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc
@@ -2560,12 +2560,13 @@ } void WebContentsImpl::AboutToNavigateRenderFrame( - RenderFrameHostImpl* render_frame_host) { + RenderFrameHostImpl* old_host, + RenderFrameHostImpl* new_host) { // Notify observers that we will navigate in this RenderFrame. FOR_EACH_OBSERVER( WebContentsObserver, observers_, - AboutToNavigateRenderFrame(render_frame_host)); + AboutToNavigateRenderFrame(old_host, new_host)); } void WebContentsImpl::DidStartNavigationToPendingEntry( @@ -2762,18 +2763,21 @@ } void WebContentsImpl::OnDocumentLoadedInFrame() { - CHECK(render_frame_message_source_); - CHECK(!render_view_message_source_); + if (!render_frame_message_source_) { + RecordAction(base::UserMetricsAction("BadMessageTerminate_WC")); + GetRenderProcessHost()->ReceivedBadMessage(); + return; + } + RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(render_frame_message_source_); FOR_EACH_OBSERVER( WebContentsObserver, observers_, DocumentLoadedInFrame(rfh)); } -void WebContentsImpl::OnDidFinishLoad( - const GURL& url) { +void WebContentsImpl::OnDidFinishLoad(const GURL& url) { if (!render_frame_message_source_) { - RecordAction(base::UserMetricsAction("BadMessageTerminate_RVD2")); + RecordAction(base::UserMetricsAction("BadMessageTerminate_WC")); GetRenderProcessHost()->ReceivedBadMessage(); return; }
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h index 5db6b0d..4248c356 100644 --- a/content/browser/web_contents/web_contents_impl.h +++ b/content/browser/web_contents/web_contents_impl.h
@@ -522,7 +522,8 @@ bool CanOverscrollContent() const override; void NotifyChangedNavigationState(InvalidateTypes changed_flags) override; void AboutToNavigateRenderFrame( - RenderFrameHostImpl* render_frame_host) override; + RenderFrameHostImpl* old_host, + RenderFrameHostImpl* new_host) override; void DidStartNavigationToPendingEntry( RenderFrameHostImpl* render_frame_host, const GURL& url,
diff --git a/content/browser/webui/shared_resources_data_source.cc b/content/browser/webui/shared_resources_data_source.cc index 66fe0f1..e11c6b1 100644 --- a/content/browser/webui/shared_resources_data_source.cc +++ b/content/browser/webui/shared_resources_data_source.cc
@@ -85,17 +85,8 @@ scoped_refptr<base::RefCountedMemory> bytes; if (idr == IDR_WEBUI_CSS_TEXT_DEFAULTS) { - std::vector<std::string> placeholders; - placeholders.push_back(webui::GetTextDirection()); // $1 - placeholders.push_back(webui::GetFontFamily()); // $2 - placeholders.push_back(webui::GetFontSize()); // $3 - - ContentClient* content_client = GetContentClient(); - const std::string& chrome_shared = - content_client->GetDataResource(idr, ui::SCALE_FACTOR_NONE).as_string(); - std::string replaced = - ReplaceStringPlaceholders(chrome_shared, placeholders, nullptr); - bytes = base::RefCountedString::TakeString(&replaced); + std::string css = webui::GetWebUiCssTextDefaults(); + bytes = base::RefCountedString::TakeString(&css); } else { bytes = GetContentClient()->GetDataResourceBytes(idr); }
diff --git a/content/browser/webui/web_ui_data_source_impl.cc b/content/browser/webui/web_ui_data_source_impl.cc index bbe54f6..8d8f4658 100644 --- a/content/browser/webui/web_ui_data_source_impl.cc +++ b/content/browser/webui/web_ui_data_source_impl.cc
@@ -11,7 +11,7 @@ #include "base/strings/string_util.h" #include "content/grit/content_resources.h" #include "content/public/common/content_client.h" -#include "mojo/public/js/constants.h" +#include "third_party/mojo/src/mojo/public/js/constants.h" #include "ui/base/webui/jstemplate_builder.h" #include "ui/base/webui/web_ui_util.h"
diff --git a/content/browser/webui/web_ui_mojo_browsertest.cc b/content/browser/webui/web_ui_mojo_browsertest.cc index 274d4c1..847e39e7 100644 --- a/content/browser/webui/web_ui_mojo_browsertest.cc +++ b/content/browser/webui/web_ui_mojo_browsertest.cc
@@ -25,10 +25,10 @@ #include "content/public/test/content_browser_test_utils.h" #include "content/shell/browser/shell.h" #include "content/test/data/web_ui_test_mojo_bindings.mojom.h" -#include "mojo/edk/test/test_utils.h" -#include "mojo/public/cpp/bindings/interface_impl.h" -#include "mojo/public/cpp/bindings/interface_request.h" -#include "mojo/public/js/constants.h" +#include "third_party/mojo/src/mojo/edk/test/test_utils.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_impl.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h" +#include "third_party/mojo/src/mojo/public/js/constants.h" namespace content { namespace {
diff --git a/content/browser/zygote_host/zygote_host_impl_linux.cc b/content/browser/zygote_host/zygote_host_impl_linux.cc index 2a2339b..f9e69a2 100644 --- a/content/browser/zygote_host/zygote_host_impl_linux.cc +++ b/content/browser/zygote_host/zygote_host_impl_linux.cc
@@ -187,15 +187,15 @@ fds[0], kZygoteHelloMessage, sizeof(kZygoteHelloMessage), &pid_)); CHECK_GT(pid_, 1); - if (process.pid() != pid_) { + if (process.Pid() != pid_) { // Reap the sandbox. - base::EnsureProcessGetsReaped(process.pid()); + base::EnsureProcessGetsReaped(process.Pid()); } } else { // Not using the SUID sandbox. // Note that ~base::Process() will reset the internal value, but there's no // real "handle" on POSIX so that is safe. - pid_ = process.pid(); + pid_ = process.Pid(); } close(fds[1]); @@ -481,7 +481,7 @@ sandbox_helper_process = base::LaunchProcess(adj_oom_score_cmdline, options); if (sandbox_helper_process.IsValid()) - base::EnsureProcessGetsReaped(sandbox_helper_process.pid()); + base::EnsureProcessGetsReaped(sandbox_helper_process.Pid()); } else if (!using_suid_sandbox_) { if (!base::AdjustOOMScore(pid, score)) PLOG(ERROR) << "Failed to adjust OOM score of renderer with pid " << pid;
diff --git a/content/child/child_discardable_shared_memory_manager.cc b/content/child/child_discardable_shared_memory_manager.cc index d5b97a0..7d07e327 100644 --- a/content/child/child_discardable_shared_memory_manager.cc +++ b/content/child/child_discardable_shared_memory_manager.cc
@@ -72,10 +72,11 @@ // Attempt to lock |free_span|. Delete span and search free list again // if locking failed. - if (!free_span->shared_memory()->Lock( + if (free_span->shared_memory()->Lock( free_span->start() * base::GetPageSize() - reinterpret_cast<size_t>(free_span->shared_memory()->memory()), - free_span->length() * base::GetPageSize())) { + free_span->length() * base::GetPageSize()) != + base::DiscardableSharedMemory::SUCCESS) { heap_.DeleteSpan(free_span.Pass()); continue; } @@ -114,19 +115,34 @@ bool ChildDiscardableSharedMemoryManager::LockSpan( DiscardableSharedMemoryHeap::Span* span) { base::AutoLock lock(lock_); - return span->shared_memory()->Lock( - span->start() * base::GetPageSize() - - reinterpret_cast<size_t>(span->shared_memory()->memory()), - span->length() * base::GetPageSize()); + + size_t offset = span->start() * base::GetPageSize() - + reinterpret_cast<size_t>(span->shared_memory()->memory()); + size_t length = span->length() * base::GetPageSize(); + + switch (span->shared_memory()->Lock(offset, length)) { + case base::DiscardableSharedMemory::SUCCESS: + return true; + case base::DiscardableSharedMemory::PURGED: + span->shared_memory()->Unlock(offset, length); + return false; + case base::DiscardableSharedMemory::FAILED: + return false; + } + + NOTREACHED(); + return false; } void ChildDiscardableSharedMemoryManager::UnlockSpan( DiscardableSharedMemoryHeap::Span* span) { base::AutoLock lock(lock_); - return span->shared_memory()->Unlock( - span->start() * base::GetPageSize() - - reinterpret_cast<size_t>(span->shared_memory()->memory()), - span->length() * base::GetPageSize()); + + size_t offset = span->start() * base::GetPageSize() - + reinterpret_cast<size_t>(span->shared_memory()->memory()); + size_t length = span->length() * base::GetPageSize(); + + return span->shared_memory()->Unlock(offset, length); } bool ChildDiscardableSharedMemoryManager::IsSpanResident(
diff --git a/content/child/mojo/mojo_application.h b/content/child/mojo/mojo_application.h index 8aee2e8..481c072 100644 --- a/content/child/mojo/mojo_application.h +++ b/content/child/mojo/mojo_application.h
@@ -7,7 +7,7 @@ #include "content/common/mojo/service_registry_impl.h" #include "ipc/ipc_platform_file.h" -#include "mojo/edk/embedder/channel_init.h" +#include "third_party/mojo/src/mojo/edk/embedder/channel_init.h" namespace IPC { class Message;
diff --git a/content/child/navigator_connect/navigator_connect_provider.cc b/content/child/navigator_connect/navigator_connect_provider.cc index 04c3b80..c928097 100644 --- a/content/child/navigator_connect/navigator_connect_provider.cc +++ b/content/child/navigator_connect/navigator_connect_provider.cc
@@ -10,7 +10,7 @@ #include "content/child/thread_safe_sender.h" #include "content/child/webmessageportchannel_impl.h" #include "content/common/navigator_connect_messages.h" -#include "content/common/navigator_connect_types.h" +#include "content/public/common/navigator_connect_client.h" #include "third_party/WebKit/public/platform/WebURL.h" namespace content { @@ -46,7 +46,7 @@ int message_port_id) { sender->Send(new NavigatorConnectHostMsg_Connect( thread_id, request_id, - CrossOriginServiceWorkerClient(target_url, origin, message_port_id))); + NavigatorConnectClient(target_url, origin, message_port_id))); } } // namespace
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc index 0d1615e..baf7019 100644 --- a/content/child/runtime_features.cc +++ b/content/child/runtime_features.cc
@@ -118,8 +118,8 @@ WebRuntimeFeatures::enableWebAudio(false); #endif - if (command_line.HasSwitch(switches::kEnableEncryptedMedia)) - WebRuntimeFeatures::enableEncryptedMedia(true); + if (command_line.HasSwitch(switches::kDisableEncryptedMedia)) + WebRuntimeFeatures::enableEncryptedMedia(false); if (command_line.HasSwitch(switches::kDisablePrefixedEncryptedMedia)) WebRuntimeFeatures::enablePrefixedEncryptedMedia(false);
diff --git a/content/child/service_worker/service_worker_dispatcher.cc b/content/child/service_worker/service_worker_dispatcher.cc index 0a30cfb..f33b86a 100644 --- a/content/child/service_worker/service_worker_dispatcher.cc +++ b/content/child/service_worker/service_worker_dispatcher.cc
@@ -57,6 +57,8 @@ void ServiceWorkerDispatcher::OnMessageReceived(const IPC::Message& msg) { bool handled = true; IPC_BEGIN_MESSAGE_MAP(ServiceWorkerDispatcher, msg) + IPC_MESSAGE_HANDLER(ServiceWorkerMsg_AssociateRegistrationWithServiceWorker, + OnAssociateRegistrationWithServiceWorker) IPC_MESSAGE_HANDLER(ServiceWorkerMsg_AssociateRegistration, OnAssociateRegistration) IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DisassociateRegistration, @@ -300,6 +302,27 @@ return new WebServiceWorkerRegistrationImpl(handle_ref.Pass()); } +// We can assume that this message handler is called before the worker context +// starts because script loading happens after this association. +// TODO(nhiroki): This association information could be pushed into +// EmbeddedWorkerMsg_StartWorker message and handed over to the worker thread +// without a lock in ServiceWorkerProviderContext. +void ServiceWorkerDispatcher::OnAssociateRegistrationWithServiceWorker( + int thread_id, + int provider_id, + const ServiceWorkerRegistrationObjectInfo& info, + const ServiceWorkerVersionAttributes& attrs) { + DCHECK_EQ(kDocumentMainThreadId, thread_id); + + ProviderContextMap::iterator context = provider_contexts_.find(provider_id); + if (context == provider_contexts_.end()) + return; + context->second->OnAssociateRegistration(info, attrs); + + // We don't have to add entries into |worker_to_provider_| because state + // change events for the workers will be notified on the worker thread. +} + void ServiceWorkerDispatcher::OnAssociateRegistration( int thread_id, int provider_id,
diff --git a/content/child/service_worker/service_worker_dispatcher.h b/content/child/service_worker/service_worker_dispatcher.h index 5ad6e35..3f1deff 100644 --- a/content/child/service_worker/service_worker_dispatcher.h +++ b/content/child/service_worker/service_worker_dispatcher.h
@@ -151,6 +151,11 @@ // WorkerTaskRunner::Observer implementation. void OnWorkerRunLoopStopped() override; + void OnAssociateRegistrationWithServiceWorker( + int thread_id, + int provider_id, + const ServiceWorkerRegistrationObjectInfo& info, + const ServiceWorkerVersionAttributes& attrs); void OnAssociateRegistration(int thread_id, int provider_id, const ServiceWorkerRegistrationObjectInfo& info,
diff --git a/content/child/service_worker/service_worker_provider_context.cc b/content/child/service_worker/service_worker_provider_context.cc index 326b25b6..f37cc65c 100644 --- a/content/child/service_worker/service_worker_provider_context.cc +++ b/content/child/service_worker/service_worker_provider_context.cc
@@ -33,6 +33,7 @@ ServiceWorkerProviderContext::~ServiceWorkerProviderContext() { if (ServiceWorkerDispatcher* dispatcher = ServiceWorkerDispatcher::GetThreadSpecificInstance()) { + // Remove this context from the dispatcher living on the main thread. dispatcher->RemoveProviderContext(this); } } @@ -44,12 +45,15 @@ ServiceWorkerRegistrationHandleReference* ServiceWorkerProviderContext::registration() { - DCHECK(main_thread_loop_proxy_->RunsTasksOnCurrentThread()); + base::AutoLock lock(lock_); return registration_.get(); } ServiceWorkerVersionAttributes ServiceWorkerProviderContext::GetVersionAttributes() { + base::AutoLock lock(lock_); + DCHECK(registration_); + ServiceWorkerVersionAttributes attrs; if (installing_) attrs.installing = installing_->info(); @@ -63,6 +67,7 @@ void ServiceWorkerProviderContext::SetVersionAttributes( ChangedVersionAttributesMask mask, const ServiceWorkerVersionAttributes& attrs) { + base::AutoLock lock(lock_); DCHECK(main_thread_loop_proxy_->RunsTasksOnCurrentThread()); DCHECK(registration_); @@ -83,6 +88,7 @@ void ServiceWorkerProviderContext::OnAssociateRegistration( const ServiceWorkerRegistrationObjectInfo& info, const ServiceWorkerVersionAttributes& attrs) { + base::AutoLock lock(lock_); DCHECK(main_thread_loop_proxy_->RunsTasksOnCurrentThread()); DCHECK(!registration_); DCHECK_NE(kInvalidServiceWorkerRegistrationId, info.registration_id); @@ -99,7 +105,9 @@ } void ServiceWorkerProviderContext::OnDisassociateRegistration() { + base::AutoLock lock(lock_); DCHECK(main_thread_loop_proxy_->RunsTasksOnCurrentThread()); + controller_.reset(); active_.reset(); waiting_.reset(); @@ -110,6 +118,7 @@ void ServiceWorkerProviderContext::OnServiceWorkerStateChanged( int handle_id, blink::WebServiceWorkerState state) { + base::AutoLock lock(lock_); DCHECK(main_thread_loop_proxy_->RunsTasksOnCurrentThread()); ServiceWorkerHandleReference* which = NULL; @@ -176,4 +185,12 @@ : kInvalidServiceWorkerRegistrationHandleId; } +void ServiceWorkerProviderContext::DestructOnMainThread() const { + if (!main_thread_loop_proxy_->RunsTasksOnCurrentThread() && + main_thread_loop_proxy_->DeleteSoon(FROM_HERE, this)) { + return; + } + delete this; +} + } // namespace content
diff --git a/content/child/service_worker/service_worker_provider_context.h b/content/child/service_worker/service_worker_provider_context.h index 03a1d28..e858ea9e 100644 --- a/content/child/service_worker/service_worker_provider_context.h +++ b/content/child/service_worker/service_worker_provider_context.h
@@ -28,13 +28,12 @@ struct ServiceWorkerProviderContextDeleter; class ThreadSafeSender; -// An instance of this class holds document-related information (e.g. -// .controller). Created and destructed on the main thread. -// TODO(kinuko): To support navigator.serviceWorker in dedicated workers -// this needs to be RefCountedThreadSafe and .controller info needs to be -// handled in a thread-safe manner (e.g. by a lock etc). +// An instance of this class holds information related to Document/Worker. +// Created and destructed on the main thread. Some functions can be called +// on the worker thread (eg. GetVersionAttributes). class ServiceWorkerProviderContext - : public base::RefCounted<ServiceWorkerProviderContext> { + : public base::RefCountedThreadSafe<ServiceWorkerProviderContext, + ServiceWorkerProviderContextDeleter> { public: explicit ServiceWorkerProviderContext(int provider_id); @@ -81,21 +80,39 @@ int registration_handle_id() const; private: - friend class base::RefCounted<ServiceWorkerProviderContext>; + friend class base::DeleteHelper<ServiceWorkerProviderContext>; + friend class base::RefCountedThreadSafe<ServiceWorkerProviderContext, + ServiceWorkerProviderContextDeleter>; + friend struct ServiceWorkerProviderContextDeleter; + ~ServiceWorkerProviderContext(); + void DestructOnMainThread() const; const int provider_id_; scoped_refptr<base::MessageLoopProxy> main_thread_loop_proxy_; scoped_refptr<ThreadSafeSender> thread_safe_sender_; + + // Protects (installing, waiting, active) worker and registration references. + base::Lock lock_; + + // Used on both the main thread and the worker thread. scoped_ptr<ServiceWorkerHandleReference> installing_; scoped_ptr<ServiceWorkerHandleReference> waiting_; scoped_ptr<ServiceWorkerHandleReference> active_; - scoped_ptr<ServiceWorkerHandleReference> controller_; scoped_ptr<ServiceWorkerRegistrationHandleReference> registration_; + // Used only on the main thread. + scoped_ptr<ServiceWorkerHandleReference> controller_; + DISALLOW_COPY_AND_ASSIGN(ServiceWorkerProviderContext); }; +struct ServiceWorkerProviderContextDeleter { + static void Destruct(const ServiceWorkerProviderContext* context) { + context->DestructOnMainThread(); + } +}; + } // namespace content #endif // CONTENT_CHILD_SERVICE_WORKER_SERVICE_WORKER_PROVIDER_CONTEXT_H_
diff --git a/content/child/shared_worker_devtools_agent.cc b/content/child/shared_worker_devtools_agent.cc index 5d127378..3a9b3509 100644 --- a/content/child/shared_worker_devtools_agent.cc +++ b/content/child/shared_worker_devtools_agent.cc
@@ -44,28 +44,37 @@ } void SharedWorkerDevToolsAgent::SendDevToolsMessage( - const blink::WebString& message) { - std::string msg(message.utf8()); + int call_id, + const blink::WebString& msg, + const blink::WebString& state) { + std::string message = msg.utf8(); + std::string post_state = state.utf8(); + DevToolsMessageChunk chunk; + chunk.message_size = message.size(); + chunk.is_first = true; + if (message.length() < kMaxMessageChunkSize) { + chunk.data.swap(message); + chunk.call_id = call_id; + chunk.post_state = post_state; + chunk.is_last = true; Send(new DevToolsClientMsg_DispatchOnInspectorFrontend( - route_id_, msg, msg.size())); + route_id_, chunk)); return; } - for (size_t pos = 0; pos < msg.length(); pos += kMaxMessageChunkSize) { + for (size_t pos = 0; pos < message.length(); pos += kMaxMessageChunkSize) { + chunk.is_last = pos + kMaxMessageChunkSize >= message.length(); + chunk.call_id = chunk.is_last ? call_id : 0; + chunk.post_state = chunk.is_last ? post_state : std::string(); + chunk.data = message.substr(pos, kMaxMessageChunkSize); Send(new DevToolsClientMsg_DispatchOnInspectorFrontend( - route_id_, - msg.substr(pos, kMaxMessageChunkSize), - pos ? 0 : msg.size())); + route_id_, chunk)); + chunk.is_first = false; + chunk.message_size = 0; } } -void SharedWorkerDevToolsAgent::SaveDevToolsAgentState( - const blink::WebString& state) { - Send(new DevToolsHostMsg_SaveAgentRuntimeState(route_id_, - state.utf8())); -} - void SharedWorkerDevToolsAgent::OnAttach(const std::string& host_id) { webworker_->attachDevTools(WebString::fromUTF8(host_id)); }
diff --git a/content/child/shared_worker_devtools_agent.h b/content/child/shared_worker_devtools_agent.h index a2d028e7..2d6a732a 100644 --- a/content/child/shared_worker_devtools_agent.h +++ b/content/child/shared_worker_devtools_agent.h
@@ -27,8 +27,9 @@ // Called on the Worker thread. bool OnMessageReceived(const IPC::Message& message); - void SendDevToolsMessage(const blink::WebString&); - void SaveDevToolsAgentState(const blink::WebString& state); + void SendDevToolsMessage(int call_id, + const blink::WebString& message, + const blink::WebString& post_state); private: void OnAttach(const std::string& host_id);
diff --git a/content/child/web_data_consumer_handle_impl.cc b/content/child/web_data_consumer_handle_impl.cc index ab97b57..a26656ed 100644 --- a/content/child/web_data_consumer_handle_impl.cc +++ b/content/child/web_data_consumer_handle_impl.cc
@@ -7,7 +7,7 @@ #include <limits> #include "base/bind.h" #include "base/logging.h" -#include "mojo/public/c/system/types.h" +#include "third_party/mojo/src/mojo/public/c/system/types.h" namespace content {
diff --git a/content/child/web_data_consumer_handle_impl.h b/content/child/web_data_consumer_handle_impl.h index 5edef3f..53038758 100644 --- a/content/child/web_data_consumer_handle_impl.h +++ b/content/child/web_data_consumer_handle_impl.h
@@ -8,8 +8,8 @@ #include "base/memory/scoped_ptr.h" #include "content/common/content_export.h" #include "mojo/common/handle_watcher.h" -#include "mojo/public/cpp/system/data_pipe.h" #include "third_party/WebKit/public/platform/WebDataConsumerHandle.h" +#include "third_party/mojo/src/mojo/public/cpp/system/data_pipe.h" namespace content {
diff --git a/content/child/web_data_consumer_handle_impl_unittest.cc b/content/child/web_data_consumer_handle_impl_unittest.cc index 7ad9d40..4aaa4dc 100644 --- a/content/child/web_data_consumer_handle_impl_unittest.cc +++ b/content/child/web_data_consumer_handle_impl_unittest.cc
@@ -12,8 +12,8 @@ #include "base/run_loop.h" #include "base/synchronization/waitable_event.h" #include "base/threading/thread.h" -#include "mojo/public/cpp/system/data_pipe.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/mojo/src/mojo/public/cpp/system/data_pipe.h" namespace content {
diff --git a/content/child/web_url_loader_impl.cc b/content/child/web_url_loader_impl.cc index 59574b3..1f852bd 100644 --- a/content/child/web_url_loader_impl.cc +++ b/content/child/web_url_loader_impl.cc
@@ -31,7 +31,6 @@ #include "content/common/service_worker/service_worker_types.h" #include "content/public/child/request_peer.h" #include "content/public/common/content_switches.h" -#include "mojo/public/cpp/system/data_pipe.h" #include "net/base/data_url.h" #include "net/base/filename_util.h" #include "net/base/mime_util.h" @@ -48,6 +47,7 @@ #include "third_party/WebKit/public/platform/WebURLRequest.h" #include "third_party/WebKit/public/platform/WebURLResponse.h" #include "third_party/WebKit/public/web/WebSecurityPolicy.h" +#include "third_party/mojo/src/mojo/public/cpp/system/data_pipe.h" using base::Time; using base::TimeTicks;
diff --git a/content/child/webblobregistry_impl.cc b/content/child/webblobregistry_impl.cc index d673c2a6..81a1f4b6 100644 --- a/content/child/webblobregistry_impl.cc +++ b/content/child/webblobregistry_impl.cc
@@ -12,7 +12,7 @@ #include "content/child/child_thread.h" #include "content/child/thread_safe_sender.h" #include "content/common/fileapi/webblob_messages.h" -#include "storage/common/blob/blob_data.h" +#include "storage/common/data_element.h" #include "third_party/WebKit/public/platform/WebBlobData.h" #include "third_party/WebKit/public/platform/WebString.h" #include "third_party/WebKit/public/platform/WebThreadSafeData.h" @@ -43,58 +43,65 @@ const blink::WebString& uuid, const blink::WebBlobData& data) { const std::string uuid_str(uuid.utf8()); + storage::DataElement data_buffer; + data_buffer.SetToEmptyBytes(); + sender_->Send(new BlobHostMsg_StartBuilding(uuid_str)); size_t i = 0; WebBlobData::Item data_item; while (data.itemAt(i++, data_item)) { + if (data_item.length == 0) { + continue; + } + if (data_item.type != WebBlobData::Item::TypeData && + data_buffer.length() != 0) { + FlushBlobItemBuffer(uuid_str, &data_buffer); + } + storage::DataElement item; switch (data_item.type) { case WebBlobData::Item::TypeData: { // WebBlobData does not allow partial data items. DCHECK(!data_item.offset && data_item.length == -1); - SendDataForBlob(uuid_str, data_item.data); + if (data_item.data.size() == 0) { + continue; + } + BufferBlobData(uuid_str, data_item.data, &data_buffer); break; } case WebBlobData::Item::TypeFile: - if (data_item.length) { - storage::BlobData::Item item; - item.SetToFilePathRange( - base::FilePath::FromUTF16Unsafe(data_item.filePath), - static_cast<uint64>(data_item.offset), - static_cast<uint64>(data_item.length), - base::Time::FromDoubleT(data_item.expectedModificationTime)); - sender_->Send( - new BlobHostMsg_AppendBlobDataItem(uuid_str, item)); - } + item.SetToFilePathRange( + base::FilePath::FromUTF16Unsafe(data_item.filePath), + static_cast<uint64>(data_item.offset), + static_cast<uint64>(data_item.length), + base::Time::FromDoubleT(data_item.expectedModificationTime)); + sender_->Send(new BlobHostMsg_AppendBlobDataItem(uuid_str, item)); break; case WebBlobData::Item::TypeBlob: - if (data_item.length) { - storage::BlobData::Item item; - item.SetToBlobRange( - data_item.blobUUID.utf8(), - static_cast<uint64>(data_item.offset), - static_cast<uint64>(data_item.length)); - sender_->Send( - new BlobHostMsg_AppendBlobDataItem(uuid_str, item)); - } + item.SetToBlobRange( + data_item.blobUUID.utf8(), + static_cast<uint64>(data_item.offset), + static_cast<uint64>(data_item.length)); + sender_->Send( + new BlobHostMsg_AppendBlobDataItem(uuid_str, item)); break; case WebBlobData::Item::TypeFileSystemURL: - if (data_item.length) { - // We only support filesystem URL as of now. - DCHECK(GURL(data_item.fileSystemURL).SchemeIsFileSystem()); - storage::BlobData::Item item; - item.SetToFileSystemUrlRange( - data_item.fileSystemURL, - static_cast<uint64>(data_item.offset), - static_cast<uint64>(data_item.length), - base::Time::FromDoubleT(data_item.expectedModificationTime)); - sender_->Send( - new BlobHostMsg_AppendBlobDataItem(uuid_str, item)); - } + // We only support filesystem URL as of now. + DCHECK(GURL(data_item.fileSystemURL).SchemeIsFileSystem()); + item.SetToFileSystemUrlRange( + data_item.fileSystemURL, + static_cast<uint64>(data_item.offset), + static_cast<uint64>(data_item.length), + base::Time::FromDoubleT(data_item.expectedModificationTime)); + sender_->Send( + new BlobHostMsg_AppendBlobDataItem(uuid_str, item)); break; default: NOTREACHED(); } } + if (data_buffer.length() != 0) { + FlushBlobItemBuffer(uuid_str, &data_buffer); + } sender_->Send(new BlobHostMsg_FinishBuilding( uuid_str, data.contentType().utf8().data())); } @@ -116,37 +123,55 @@ sender_->Send(new BlobHostMsg_RevokePublicURL(url)); } -void WebBlobRegistryImpl::SendDataForBlob(const std::string& uuid_str, - const WebThreadSafeData& data) { +void WebBlobRegistryImpl::FlushBlobItemBuffer( + const std::string& uuid_str, + storage::DataElement* data_buffer) const { + DCHECK_NE(data_buffer->length(), 0ul); + DCHECK_LT(data_buffer->length(), kLargeThresholdBytes); + sender_->Send(new BlobHostMsg_AppendBlobDataItem(uuid_str, *data_buffer)); + data_buffer->SetToEmptyBytes(); +} - if (data.size() == 0) - return; - if (data.size() < kLargeThresholdBytes) { - storage::BlobData::Item item; - item.SetToBytes(data.data(), data.size()); - sender_->Send(new BlobHostMsg_AppendBlobDataItem(uuid_str, item)); +void WebBlobRegistryImpl::BufferBlobData(const std::string& uuid_str, + const blink::WebThreadSafeData& data, + storage::DataElement* data_buffer) { + size_t buffer_size = data_buffer->length(); + size_t data_size = data.size(); + DCHECK_NE(data_size, 0ul); + if (buffer_size != 0 && buffer_size + data_size >= kLargeThresholdBytes) { + FlushBlobItemBuffer(uuid_str, data_buffer); + buffer_size = 0; + } + if (data_size >= kLargeThresholdBytes) { + SendOversizedDataForBlob(uuid_str, data); } else { - // We handle larger amounts of data via SharedMemory instead of - // writing it directly to the IPC channel. - size_t shared_memory_size = std::min( - data.size(), kMaxSharedMemoryBytes); - scoped_ptr<base::SharedMemory> shared_memory( - ChildThread::AllocateSharedMemory(shared_memory_size, - sender_.get())); - CHECK(shared_memory.get()); - if (!shared_memory->Map(shared_memory_size)) - CHECK(false); + DCHECK_LT(buffer_size + data_size, kLargeThresholdBytes); + data_buffer->AppendBytes(data.data(), data_size); + } +} - size_t data_size = data.size(); - const char* data_ptr = data.data(); - while (data_size) { - size_t chunk_size = std::min(data_size, shared_memory_size); - memcpy(shared_memory->memory(), data_ptr, chunk_size); - sender_->Send(new BlobHostMsg_SyncAppendSharedMemory( - uuid_str, shared_memory->handle(), chunk_size)); - data_size -= chunk_size; - data_ptr += chunk_size; - } +void WebBlobRegistryImpl::SendOversizedDataForBlob( + const std::string& uuid_str, + const blink::WebThreadSafeData& data) { + DCHECK_GE(data.size(), kLargeThresholdBytes); + // We handle larger amounts of data via SharedMemory instead of + // writing it directly to the IPC channel. + size_t shared_memory_size = std::min(data.size(), kMaxSharedMemoryBytes); + scoped_ptr<base::SharedMemory> shared_memory( + ChildThread::AllocateSharedMemory(shared_memory_size, sender_.get())); + CHECK(shared_memory.get()); + if (!shared_memory->Map(shared_memory_size)) + CHECK(false); + + size_t data_size = data.size(); + const char* data_ptr = data.data(); + while (data_size) { + size_t chunk_size = std::min(data_size, shared_memory_size); + memcpy(shared_memory->memory(), data_ptr, chunk_size); + sender_->Send(new BlobHostMsg_SyncAppendSharedMemory( + uuid_str, shared_memory->handle(), chunk_size)); + data_size -= chunk_size; + data_ptr += chunk_size; } } @@ -170,7 +195,7 @@ if (length == 0) return; if (length < kLargeThresholdBytes) { - storage::BlobData::Item item; + storage::DataElement item; item.SetToBytes(data, length); sender_->Send(new StreamHostMsg_AppendBlobDataItem(url, item)); } else {
diff --git a/content/child/webblobregistry_impl.h b/content/child/webblobregistry_impl.h index e438baa..dc67128 100644 --- a/content/child/webblobregistry_impl.h +++ b/content/child/webblobregistry_impl.h
@@ -6,6 +6,7 @@ #define CONTENT_CHILD_WEBBLOBREGISTRY_IMPL_H_ #include <string> +#include <vector> #include "base/memory/ref_counted.h" #include "third_party/WebKit/public/platform/WebBlobRegistry.h" @@ -14,6 +15,10 @@ class WebThreadSafeData; } // namespace blink +namespace storage { +class DataElement; +} + namespace content { class ThreadSafeSender; @@ -43,8 +48,19 @@ virtual void unregisterStreamURL(const blink::WebURL& url); private: - void SendDataForBlob(const std::string& uuid_str, - const blink::WebThreadSafeData& data); + // Sends the data in the buffer as a blob item, then resets the buffer size. + void FlushBlobItemBuffer(const std::string& uuid_str, + storage::DataElement* data_buffer) const; + + // Adds the item to the consolidating buffer, flushing the buffer if needed. + // If the item is too big for the buffer, it is sent as Sync messages in + // shared memory instead. + void BufferBlobData(const std::string& uuid_str, + const blink::WebThreadSafeData& data, + storage::DataElement* data_buffer); + // Sends data that is larger than the threshold. + void SendOversizedDataForBlob(const std::string& uuid_str, + const blink::WebThreadSafeData& data); scoped_refptr<ThreadSafeSender> sender_; };
diff --git a/content/child/webcrypto/openssl/pbkdf2_openssl.cc b/content/child/webcrypto/openssl/pbkdf2_openssl.cc index e25d96c..9f3017b52 100644 --- a/content/child/webcrypto/openssl/pbkdf2_openssl.cc +++ b/content/child/webcrypto/openssl/pbkdf2_openssl.cc
@@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/numerics/safe_math.h" #include "content/child/webcrypto/algorithm_implementation.h" #include "content/child/webcrypto/crypto_data.h" #include "content/child/webcrypto/openssl/key_openssl.h" @@ -84,23 +83,18 @@ if (password.empty()) return Status::ErrorPbkdf2EmptyPassword(); - // Prevent underflowing password.size() - BoringSSL expects the size as an - // signed int, and will interpret the data as a C-String if it is -1. - base::CheckedNumeric<int> password_size = password.size(); - if (!password_size.IsValid()) - return Status::ErrorDataTooLarge(); - if (keylen_bytes == 0) return Status::Success(); const char* password_ptr = password.empty() ? NULL : reinterpret_cast<const char*>(&password[0]); - if (!PKCS5_PBKDF2_HMAC(password_ptr, password_size.ValueOrDie(), - params->salt().data(), params->salt().size(), - params->iterations(), digest_algorithm, keylen_bytes, - &derived_bytes->front())) + if (!PKCS5_PBKDF2_HMAC(password_ptr, password.size(), params->salt().data(), + params->salt().size(), params->iterations(), + digest_algorithm, keylen_bytes, + &derived_bytes->front())) { return Status::OperationError(); + } return Status::Success(); }
diff --git a/content/child/webthread_impl.cc b/content/child/webthread_impl.cc index 28d687b..4f4f0e8 100644 --- a/content/child/webthread_impl.cc +++ b/content/child/webthread_impl.cc
@@ -12,6 +12,7 @@ #include "base/message_loop/message_loop.h" #include "base/pending_task.h" #include "base/threading/platform_thread.h" +#include "third_party/WebKit/public/platform/WebTraceLocation.h" namespace content { @@ -88,15 +89,29 @@ } void WebThreadImpl::postTask(Task* task) { - thread_->message_loop()->PostTask( - FROM_HERE, - base::Bind(RunWebThreadTask, base::Passed(scoped_ptr<Task>(task)))); + postDelayedTask(task, 0); +} + +void WebThreadImpl::postTask(const blink::WebTraceLocation& location, + Task* task) { + postDelayedTask(location, task, 0); } void WebThreadImpl::postDelayedTask(Task* task, long long delay_ms) { thread_->message_loop()->PostDelayedTask( FROM_HERE, - base::Bind(RunWebThreadTask, base::Passed(scoped_ptr<Task>(task))), + base::Bind(RunWebThreadTask, base::Passed(make_scoped_ptr(task))), + base::TimeDelta::FromMilliseconds(delay_ms)); +} + +void WebThreadImpl::postDelayedTask(const blink::WebTraceLocation& web_location, + Task* task, + long long delay_ms) { + tracked_objects::Location location(web_location.functionName(), + web_location.fileName(), -1, nullptr); + thread_->message_loop()->PostDelayedTask( + location, + base::Bind(RunWebThreadTask, base::Passed(make_scoped_ptr(task))), base::TimeDelta::FromMilliseconds(delay_ms)); } @@ -130,9 +145,13 @@ thread_id_(base::PlatformThread::CurrentId()) {} void WebThreadImplForMessageLoop::postTask(Task* task) { - main_thread_task_runner_->PostTask( - FROM_HERE, - base::Bind(RunWebThreadTask, base::Passed(make_scoped_ptr(task)))); + postDelayedTask(task, 0); +} + +void WebThreadImplForMessageLoop::postTask( + const blink::WebTraceLocation& location, + Task* task) { + postDelayedTask(location, task, 0); } void WebThreadImplForMessageLoop::postDelayedTask(Task* task, @@ -143,6 +162,18 @@ base::TimeDelta::FromMilliseconds(delay_ms)); } +void WebThreadImplForMessageLoop::postDelayedTask( + const blink::WebTraceLocation& web_location, + Task* task, + long long delay_ms) { + tracked_objects::Location location(web_location.functionName(), + web_location.fileName(), -1, nullptr); + main_thread_task_runner_->PostDelayedTask( + location, + base::Bind(RunWebThreadTask, base::Passed(make_scoped_ptr(task))), + base::TimeDelta::FromMilliseconds(delay_ms)); +} + void WebThreadImplForMessageLoop::enterRunLoop() { CHECK(isCurrentThread()); // We don't support nesting.
diff --git a/content/child/webthread_impl.h b/content/child/webthread_impl.h index b63d384..481ff25 100644 --- a/content/child/webthread_impl.h +++ b/content/child/webthread_impl.h
@@ -12,6 +12,10 @@ #include "content/common/content_export.h" #include "third_party/WebKit/public/platform/WebThread.h" +namespace blink { +class WebTraceLocation; +} + namespace content { class CONTENT_EXPORT WebThreadBase : public blink::WebThread { @@ -39,6 +43,12 @@ explicit WebThreadImpl(const char* name); virtual ~WebThreadImpl(); + virtual void postTask(const blink::WebTraceLocation& location, Task* task); + virtual void postDelayedTask(const blink::WebTraceLocation& location, + Task* task, + long long delay_ms); + + // TODO(skyostil): Remove once blink has migrated. virtual void postTask(Task* task); virtual void postDelayedTask(Task* task, long long delay_ms); @@ -60,8 +70,14 @@ scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner); CONTENT_EXPORT virtual ~WebThreadImplForMessageLoop(); - virtual void postTask(Task* task) override; - virtual void postDelayedTask(Task* task, long long delay_ms) override; + virtual void postTask(const blink::WebTraceLocation& location, Task* task); + virtual void postDelayedTask(const blink::WebTraceLocation& location, + Task* task, + long long delay_ms); + + // TODO(skyostil): Remove once blink has migrated. + virtual void postTask(Task* task); + virtual void postDelayedTask(Task* task, long long delay_ms); virtual void enterRunLoop() override; virtual void exitRunLoop() override;
diff --git a/content/common/cc_messages_perftest.cc b/content/common/cc_messages_perftest.cc index 1aa09e8..78085d2 100644 --- a/content/common/cc_messages_perftest.cc +++ b/content/common/cc_messages_perftest.cc
@@ -33,7 +33,7 @@ IPC::ParamTraits<CompositorFrame>::Write(&msg, frame); } - base::TimeTicks start = base::TimeTicks::HighResNow(); + base::TimeTicks start = base::TimeTicks::Now(); base::TimeTicks end = start + base::TimeDelta::FromMilliseconds(kTimeLimitMillis); base::TimeDelta min_time; @@ -45,10 +45,10 @@ ++count; } - base::TimeTicks now = base::TimeTicks::HighResNow(); + base::TimeTicks now = base::TimeTicks::Now(); if (now - start < min_time || min_time == base::TimeDelta()) min_time = now - start; - start = base::TimeTicks::HighResNow(); + start = base::TimeTicks::Now(); } perf_test::PrintResult(
diff --git a/content/common/devtools_messages.h b/content/common/devtools_messages.h index 276a82f..ee475c8d 100644 --- a/content/common/devtools_messages.h +++ b/content/common/devtools_messages.h
@@ -54,14 +54,24 @@ // These are messages sent from DevToolsAgent to DevToolsClient through the // browser. -// WebKit-level transport. + +// Agent -> Client message chunk. +// |is_first| marks the first chunk, comes with the |message_size| for +// total message size. +// |is_last| marks the last chunk. |call_id| and |post_state| are optional +// parameters passed with the last chunk of the protocol response. +IPC_STRUCT_BEGIN(DevToolsMessageChunk) + IPC_STRUCT_MEMBER(bool, is_first) + IPC_STRUCT_MEMBER(bool, is_last) + IPC_STRUCT_MEMBER(int, message_size) + IPC_STRUCT_MEMBER(int, call_id) + IPC_STRUCT_MEMBER(std::string, data) + IPC_STRUCT_MEMBER(std::string, post_state) +IPC_STRUCT_END() // Sends response from the agent to the client. Supports chunked encoding. -// First (the only) chunk arrives with the |total_size| != 0, -// remaining chunks arrive with |total_size| == 0. -IPC_MESSAGE_ROUTED2(DevToolsClientMsg_DispatchOnInspectorFrontend, - std::string /* message */, - uint32 /* total_size */) +IPC_MESSAGE_ROUTED1(DevToolsClientMsg_DispatchOnInspectorFrontend, + DevToolsMessageChunk /* message */) //----------------------------------------------------------------------------- // These are messages sent from DevToolsClient to DevToolsAgent through the @@ -111,11 +121,6 @@ IPC_MESSAGE_ROUTED1(DevToolsHostMsg_DispatchOnEmbedder, std::string /* message */) -// Updates agent runtime state stored in devtools manager in order to support -// cross-navigation instrumentation. -IPC_MESSAGE_ROUTED1(DevToolsHostMsg_SaveAgentRuntimeState, - std::string /* state */) - //----------------------------------------------------------------------------- // These are messages sent from the GPU process to the inspected renderer.
diff --git a/content/common/dwrite_font_platform_win.cc b/content/common/dwrite_font_platform_win.cc index 0cba230..c2547b5 100644 --- a/content/common/dwrite_font_platform_win.cc +++ b/content/common/dwrite_font_platform_win.cc
@@ -69,7 +69,7 @@ // phase. If we don't use this percentile formula we will end up // increasing significant cache size by caching entire file contents // for some of the font files. -const double kMaxPercentileOfFontFileSizeToCache = 0.5; +const double kMaxPercentileOfFontFileSizeToCache = 0.6; // With current implementation we map entire shared section into memory during // renderer startup. This causes increase in working set of Chrome. As first @@ -77,14 +77,14 @@ // users, so we are putting arbitrary limit on cache file size. There are // multiple ways we can tune our working size, like mapping only required part // of section at any given time. -const double kArbitraryCacheFileSizeLimit = (20 * 1024 * 1024); +const double kArbitraryCacheFileSizeLimit = (30 * 1024 * 1024); // We have chosen current font file length arbitrarily. In our logic // if we don't find file we are looking for in cache we end up loading // that file directly from system fonts folder. const unsigned int kMaxFontFileNameLength = 34; -const DWORD kCacheFileVersion = 102; +const DWORD kCacheFileVersion = 103; const DWORD kFileSignature = 0x4D4F5243; // CROM const DWORD kMagicCompletionSignature = 0x454E4F44; // DONE
diff --git a/content/common/fileapi/webblob_messages.h b/content/common/fileapi/webblob_messages.h index aad38c3..7527b18 100644 --- a/content/common/fileapi/webblob_messages.h +++ b/content/common/fileapi/webblob_messages.h
@@ -8,7 +8,7 @@ #include "content/common/content_export.h" #include "content/public/common/common_param_traits.h" #include "ipc/ipc_message_macros.h" -#include "storage/common/blob/blob_data.h" +#include "storage/common/data_element.h" #undef IPC_MESSAGE_EXPORT #define IPC_MESSAGE_EXPORT CONTENT_EXPORT @@ -20,7 +20,7 @@ std::string /*uuid */) IPC_MESSAGE_CONTROL2(BlobHostMsg_AppendBlobDataItem, std::string /* uuid */, - storage::BlobData::Item) + storage::DataElement) IPC_SYNC_MESSAGE_CONTROL3_0(BlobHostMsg_SyncAppendSharedMemory, std::string /*uuid*/, base::SharedMemoryHandle, @@ -49,7 +49,7 @@ // Appends data to a stream being built. IPC_MESSAGE_CONTROL2(StreamHostMsg_AppendBlobDataItem, GURL /* url */, - storage::BlobData::Item) + storage::DataElement) // Appends data to a stream being built. IPC_SYNC_MESSAGE_CONTROL3_0(StreamHostMsg_SyncAppendSharedMemory,
diff --git a/content/common/font_config_ipc_linux.cc b/content/common/font_config_ipc_linux.cc index c64aebf66..8de951b 100644 --- a/content/common/font_config_ipc_linux.cc +++ b/content/common/font_config_ipc_linux.cc
@@ -20,11 +20,12 @@ #include "skia/ext/skia_utils_base.h" #include "third_party/skia/include/core/SkData.h" #include "third_party/skia/include/core/SkStream.h" +#include "third_party/skia/include/core/SkTypeface.h" namespace content { // Return a stream from the file descriptor, or NULL on failure. -SkStream* StreamFromFD(int fd) { +SkStreamAsset* StreamFromFD(int fd) { skia::RefPtr<SkData> data = skia::AdoptRef(SkData::NewFromFD(fd)); if (!data) { return NULL; @@ -94,7 +95,7 @@ return true; } -SkStream* FontConfigIPC::openStream(const FontIdentity& identity) { +SkStreamAsset* FontConfigIPC::openStream(const FontIdentity& identity) { TRACE_EVENT0("sandbox_ipc", "FontConfigIPC::openStream"); Pickle request; request.WriteInt(METHOD_OPEN); @@ -118,7 +119,7 @@ return NULL; } - SkStream* stream = StreamFromFD(result_fd); + SkStreamAsset* stream = StreamFromFD(result_fd); CloseFD(result_fd); return stream; }
diff --git a/content/common/font_config_ipc_linux.h b/content/common/font_config_ipc_linux.h index c5cf80f..1708286 100644 --- a/content/common/font_config_ipc_linux.h +++ b/content/common/font_config_ipc_linux.h
@@ -6,10 +6,14 @@ #define CONTENT_COMMON_FONT_CONFIG_IPC_LINUX_H_ #include "base/compiler_specific.h" +#include "third_party/skia/include/core/SkStream.h" +#include "third_party/skia/include/core/SkTypeface.h" #include "third_party/skia/include/ports/SkFontConfigInterface.h" #include <string> +class SkString; + namespace content { // FontConfig implementation for Skia that proxies out of process to get out @@ -25,7 +29,7 @@ SkString* outFamilyName, SkTypeface::Style* outStyle) override; - SkStream* openStream(const FontIdentity&) override; + SkStreamAsset* openStream(const FontIdentity&) override; enum Method { METHOD_MATCH = 0,
diff --git a/content/common/frame_message_enums.h b/content/common/frame_message_enums.h index 4349a04..a535113 100644 --- a/content/common/frame_message_enums.h +++ b/content/common/frame_message_enums.h
@@ -46,7 +46,10 @@ // Report metrics for this load, that originated from clicking on a link. REPORT_LINK, - REPORT_TYPE_LAST = REPORT_LINK, + // Report metrics for this load, that originated from an Android OS intent. + REPORT_INTENT, + + REPORT_TYPE_LAST = REPORT_INTENT, }; };
diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h index 0e21380..d22c7043 100644 --- a/content/common/frame_messages.h +++ b/content/common/frame_messages.h
@@ -210,6 +210,8 @@ IPC_STRUCT_TRAITS_MEMBER(transition) IPC_STRUCT_TRAITS_MEMBER(navigation_type) IPC_STRUCT_TRAITS_MEMBER(allow_download) + IPC_STRUCT_TRAITS_MEMBER(ui_timestamp) + IPC_STRUCT_TRAITS_MEMBER(report_type) IPC_STRUCT_TRAITS_END() IPC_STRUCT_TRAITS_BEGIN(content::RequestNavigationParams)
diff --git a/content/common/gpu/gpu_messages.h b/content/common/gpu/gpu_messages.h index 6e32684..09bc877 100644 --- a/content/common/gpu/gpu_messages.h +++ b/content/common/gpu/gpu_messages.h
@@ -708,7 +708,7 @@ // These messages are sent from the Renderer process to GPU process. // Queue a input buffer to the encoder to encode. |frame_id| will be returned by -// AcceleratedVideoEncoderHostMsg_NotifyEncodeDone. +// AcceleratedVideoEncoderHostMsg_NotifyInputDone. IPC_MESSAGE_ROUTED4(AcceleratedVideoEncoderMsg_Encode, int32 /* frame_id */, base::SharedMemoryHandle /* buffer_handle */,
diff --git a/content/common/gpu/media/h264_decoder.cc b/content/common/gpu/media/h264_decoder.cc index af36b03..eaf5ca4 100644 --- a/content/common/gpu/media/h264_decoder.cc +++ b/content/common/gpu/media/h264_decoder.cc
@@ -123,9 +123,9 @@ // process after this picture is decoded, store required data for that // purpose. if (slice_hdr->adaptive_ref_pic_marking_mode_flag) { - COMPILE_ASSERT(sizeof(curr_pic_->ref_pic_marking) == - sizeof(slice_hdr->ref_pic_marking), - ref_pic_marking_array_sizes_do_not_match); + static_assert(sizeof(curr_pic_->ref_pic_marking) == + sizeof(slice_hdr->ref_pic_marking), + "Array sizes of ref pic marking do not match."); memcpy(curr_pic_->ref_pic_marking, slice_hdr->ref_pic_marking, sizeof(curr_pic_->ref_pic_marking)); }
diff --git a/content/common/gpu/media/v4l2_slice_video_decode_accelerator.cc b/content/common/gpu/media/v4l2_slice_video_decode_accelerator.cc index c0d0b3a..e4f36c4 100644 --- a/content/common/gpu/media/v4l2_slice_video_decode_accelerator.cc +++ b/content/common/gpu/media/v4l2_slice_video_decode_accelerator.cc
@@ -886,10 +886,7 @@ } InputRecord& input_record = input_buffer_map_[dqbuf.index]; DCHECK(input_record.at_device); - input_record.at_device = false; - input_record.input_id = -1; - input_record.bytes_used = 0; - free_input_buffers_.push_back(dqbuf.index); + ReuseInputBuffer(dqbuf.index); input_buffer_queued_count_--; DVLOGF(4) << "Dequeued input=" << dqbuf.index << " count: " << input_buffer_queued_count_; @@ -949,6 +946,18 @@ FinishResetIfNeeded(); } +void V4L2SliceVideoDecodeAccelerator::ReuseInputBuffer(int index) { + DCHECK_LT(index, static_cast<int>(input_buffer_map_.size())); + DVLOGF(4) << "Reusing input buffer, index=" << index; + DCHECK(decoder_thread_proxy_->BelongsToCurrentThread()); + + InputRecord& input_record = input_buffer_map_[index]; + input_record.at_device = false; + input_record.input_id = -1; + input_record.bytes_used = 0; + free_input_buffers_.push_back(index); +} + void V4L2SliceVideoDecodeAccelerator::ReuseOutputBuffer(int index) { DCHECK_LT(index, static_cast<int>(output_buffer_map_.size())); DVLOGF(4) << "Reusing output buffer, index=" << index; @@ -1104,13 +1113,10 @@ if (!keep_input_state) { free_input_buffers_.clear(); - for (size_t i = 0; i < input_buffer_map_.size(); ++i) { - InputRecord& input_record = input_buffer_map_[i]; - input_record.at_device = false; - input_record.bytes_used = 0; - input_record.input_id = -1; - free_input_buffers_.push_back(i); - } + // We don't care about the buffer state (at_device) here, because + // STREAMOFF tells the driver to drop all buffers without DQBUFing them. + for (size_t i = 0; i < input_buffer_map_.size(); ++i) + ReuseInputBuffer(i); input_buffer_queued_count_ = 0; } @@ -1561,6 +1567,11 @@ // we will have all remaining PictureReady() posted to the client and we // can post NotifyFlushDone(). DCHECK(decoder_display_queue_.empty()); + + // Decoder should have already returned all surfaces and all surfaces are + // out of hardware. There can be no other owners of input buffers. + DCHECK_EQ(free_input_buffers_.size(), input_buffer_map_.size()); + SendPictureReady(); child_message_loop_proxy_->PostTask( @@ -1624,6 +1635,19 @@ while (!decoder_display_queue_.empty()) decoder_display_queue_.pop(); + // At this point we can have no input buffers in the decoder, because we + // Reset()ed it in ResetTask(), and have not scheduled any new Decode()s + // having been in kIdle since. We don't have any surfaces in the HW either - + // we just checked that surfaces_at_device_.empty(), and inputs are tied + // to surfaces. Since there can be no other owners of input buffers, we can + // simply mark them all as available. + DCHECK_EQ(input_buffer_queued_count_, 0); + free_input_buffers_.clear(); + for (size_t i = 0; i < input_buffer_map_.size(); ++i) { + DCHECK(!input_buffer_map_[i].at_device); + ReuseInputBuffer(i); + } + decoder_resetting_ = false; child_message_loop_proxy_->PostTask( @@ -2360,6 +2384,7 @@ scoped_refptr<V4L2SliceVideoDecodeAccelerator::V4L2DecodeSurface> V4L2SliceVideoDecodeAccelerator::CreateSurface() { DCHECK(decoder_thread_proxy_->BelongsToCurrentThread()); + DCHECK_EQ(state_, kDecoding); if (free_input_buffers_.empty() || free_output_buffers_.empty()) return nullptr;
diff --git a/content/common/gpu/media/v4l2_slice_video_decode_accelerator.h b/content/common/gpu/media/v4l2_slice_video_decode_accelerator.h index 85b95a70..832e1e7 100644 --- a/content/common/gpu/media/v4l2_slice_video_decode_accelerator.h +++ b/content/common/gpu/media/v4l2_slice_video_decode_accelerator.h
@@ -111,6 +111,9 @@ // // Internal methods of this class. // + // Recycle a V4L2 input buffer with |index| after dequeuing from device. + void ReuseInputBuffer(int index); + // Recycle V4L2 output buffer with |index|. Used as surface release callback. void ReuseOutputBuffer(int index);
diff --git a/content/common/gpu/media/video_decode_accelerator_unittest.cc b/content/common/gpu/media/video_decode_accelerator_unittest.cc index 3b9ec20..71db758 100644 --- a/content/common/gpu/media/video_decode_accelerator_unittest.cc +++ b/content/common/gpu/media/video_decode_accelerator_unittest.cc
@@ -262,21 +262,21 @@ int delay_reuse_after_frame_num, int decode_calls_per_second, bool render_as_thumbnails); - virtual ~GLRenderingVDAClient(); + ~GLRenderingVDAClient() override; void CreateAndStartDecoder(); // VideoDecodeAccelerator::Client implementation. // The heart of the Client. - virtual void ProvidePictureBuffers(uint32 requested_num_of_buffers, - const gfx::Size& dimensions, - uint32 texture_target) override; - virtual void DismissPictureBuffer(int32 picture_buffer_id) override; - virtual void PictureReady(const media::Picture& picture) override; + void ProvidePictureBuffers(uint32 requested_num_of_buffers, + const gfx::Size& dimensions, + uint32 texture_target) override; + void DismissPictureBuffer(int32 picture_buffer_id) override; + void PictureReady(const media::Picture& picture) override; // Simple state changes. - virtual void NotifyEndOfBitstreamBuffer(int32 bitstream_buffer_id) override; - virtual void NotifyFlushDone() override; - virtual void NotifyResetDone() override; - virtual void NotifyError(VideoDecodeAccelerator::Error error) override; + void NotifyEndOfBitstreamBuffer(int32 bitstream_buffer_id) override; + void NotifyFlushDone() override; + void NotifyResetDone() override; + void NotifyError(VideoDecodeAccelerator::Error error) override; void OutputFrameDeliveryTimes(base::File* output); @@ -914,8 +914,8 @@ class VideoDecodeAcceleratorTest : public ::testing::Test { protected: VideoDecodeAcceleratorTest(); - virtual void SetUp(); - virtual void TearDown(); + void SetUp() override; + void TearDown() override; // Parse |data| into its constituent parts, set the various output fields // accordingly, and read in video stream. CHECK-fails on unexpected or
diff --git a/content/common/gpu/media/video_encode_accelerator_unittest.cc b/content/common/gpu/media/video_encode_accelerator_unittest.cc index e56b03b6..46804351 100644 --- a/content/common/gpu/media/video_encode_accelerator_unittest.cc +++ b/content/common/gpu/media/video_encode_accelerator_unittest.cc
@@ -20,6 +20,7 @@ #include "media/base/bitstream_buffer.h" #include "media/base/test_data_util.h" #include "media/filters/h264_parser.h" +#include "media/video/fake_video_encode_accelerator.h" #include "media/video/video_encode_accelerator.h" #include "testing/gtest/include/gtest/gtest.h" @@ -101,6 +102,11 @@ // Bitrate is only forced for tests that test bitrate. const char* g_default_in_filename = "bear_320x192_40frames.yuv"; const char* g_default_in_parameters = ":320:192:1:out.h264:200000"; + +// Enabled by including a --fake_encoder flag to the command line invoking the +// test. +bool g_fake_encoder = false; + // Environment to store test stream data for all test cases. class VideoEncodeAcceleratorTestEnvironment; VideoEncodeAcceleratorTestEnvironment* g_env; @@ -395,7 +401,7 @@ seen_pps_(false), seen_idr_(false) {} - virtual void ProcessStreamBuffer(const uint8* stream, size_t size) override; + void ProcessStreamBuffer(const uint8* stream, size_t size) override; private: // Set to true when encoder provides us with the corresponding NALU type. @@ -462,7 +468,7 @@ : StreamValidator(frame_cb), seen_keyframe_(false) {} - virtual void ProcessStreamBuffer(const uint8* stream, size_t size) override; + void ProcessStreamBuffer(const uint8* stream, size_t size) override; private: // Have we already got a keyframe in the stream? @@ -488,7 +494,9 @@ const FrameFoundCallback& frame_cb) { scoped_ptr<StreamValidator> validator; - if (IsH264(profile)) { + if (g_fake_encoder) { + validator.reset(NULL); + } else if (IsH264(profile)) { validator.reset(new H264Validator(frame_cb)); } else if (IsVP8(profile)) { validator.reset(new VP8Validator(frame_cb)); @@ -510,7 +518,7 @@ bool mid_stream_bitrate_switch, bool mid_stream_framerate_switch, bool run_at_fps); - virtual ~VEAClient(); + ~VEAClient() override; void CreateEncoder(); void DestroyEncoder(); @@ -518,17 +526,18 @@ double frames_per_second(); // VideoDecodeAccelerator::Client implementation. - virtual void RequireBitstreamBuffers(unsigned int input_count, - const gfx::Size& input_coded_size, - size_t output_buffer_size) override; - virtual void BitstreamBufferReady(int32 bitstream_buffer_id, - size_t payload_size, - bool key_frame) override; - virtual void NotifyError(VideoEncodeAccelerator::Error error) override; + void RequireBitstreamBuffers(unsigned int input_count, + const gfx::Size& input_coded_size, + size_t output_buffer_size) override; + void BitstreamBufferReady(int32 bitstream_buffer_id, + size_t payload_size, + bool key_frame) override; + void NotifyError(VideoEncodeAccelerator::Error error) override; private: bool has_encoder() { return encoder_.get(); } + scoped_ptr<media::VideoEncodeAccelerator> CreateFakeVEA(); scoped_ptr<media::VideoEncodeAccelerator> CreateV4L2VEA(); scoped_ptr<media::VideoEncodeAccelerator> CreateVaapiVEA(); @@ -716,7 +725,8 @@ test_stream_->requested_profile, base::Bind(&VEAClient::HandleEncodedFrame, base::Unretained(this))); - CHECK(validator_.get()); + + CHECK(g_fake_encoder || validator_.get()); if (save_to_file_) { CHECK(!test_stream_->out_filename.empty()); @@ -734,6 +744,17 @@ VEAClient::~VEAClient() { CHECK(!has_encoder()); } +scoped_ptr<media::VideoEncodeAccelerator> VEAClient::CreateFakeVEA() { + scoped_ptr<media::VideoEncodeAccelerator> encoder; + if (g_fake_encoder) { + encoder.reset( + new media::FakeVideoEncodeAccelerator( + scoped_refptr<base::SingleThreadTaskRunner>( + base::MessageLoopProxy::current()))); + } + return encoder.Pass(); +} + scoped_ptr<media::VideoEncodeAccelerator> VEAClient::CreateV4L2VEA() { scoped_ptr<media::VideoEncodeAccelerator> encoder; #if defined(OS_CHROMEOS) && (defined(ARCH_CPU_ARMEL) || \ @@ -758,6 +779,7 @@ CHECK(!has_encoder()); scoped_ptr<media::VideoEncodeAccelerator> encoders[] = { + CreateFakeVEA(), CreateV4L2VEA(), CreateVaapiVEA() }; @@ -911,7 +933,11 @@ const uint8* stream_ptr = static_cast<const uint8*>(shm->memory()); if (payload_size > 0) { - validator_->ProcessStreamBuffer(stream_ptr, payload_size); + if (validator_) { + validator_->ProcessStreamBuffer(stream_ptr, payload_size); + } else { + HandleEncodedFrame(key_frame); + } if (save_to_file_) { if (IsVP8(test_stream_->requested_profile)) @@ -1352,6 +1378,9 @@ if (it->first == "num_frames_to_encode") { std::string input(it->second.begin(), it->second.end()); CHECK(base::StringToInt(input, &content::g_num_frames_to_encode)); + } + if (it->first == "fake_encoder") { + content::g_fake_encoder = true; continue; } if (it->first == "run_at_fps") {
diff --git a/content/common/host_discardable_shared_memory_manager_unittest.cc b/content/common/host_discardable_shared_memory_manager_unittest.cc index 699fdd5..fc47e13 100644 --- a/content/common/host_discardable_shared_memory_manager_unittest.cc +++ b/content/common/host_discardable_shared_memory_manager_unittest.cc
@@ -78,7 +78,7 @@ memory.SetNow(base::Time::FromDoubleT(1)); memory.Unlock(0, 0); - ASSERT_TRUE(memory.Lock(0, 0)); + ASSERT_EQ(base::DiscardableSharedMemory::SUCCESS, memory.Lock(0, 0)); EXPECT_EQ(memcmp(data, memory.memory(), kDataSize), 0); memory.Unlock(0, 0); } @@ -122,10 +122,10 @@ EXPECT_TRUE(memory1.IsMemoryResident()); EXPECT_TRUE(memory2.IsMemoryResident()); - rv = memory1.Lock(0, 0); - EXPECT_TRUE(rv); - rv = memory2.Lock(0, 0); - EXPECT_TRUE(rv); + auto lock_rv = memory1.Lock(0, 0); + EXPECT_EQ(base::DiscardableSharedMemory::SUCCESS, lock_rv); + lock_rv = memory2.Lock(0, 0); + EXPECT_EQ(base::DiscardableSharedMemory::SUCCESS, lock_rv); memory1.SetNow(base::Time::FromDoubleT(4)); memory1.Unlock(0, 0); @@ -141,10 +141,10 @@ EXPECT_FALSE(memory1.IsMemoryResident()); EXPECT_TRUE(memory2.IsMemoryResident()); - rv = memory1.Lock(0, 0); - EXPECT_FALSE(rv); - rv = memory2.Lock(0, 0); - EXPECT_TRUE(rv); + lock_rv = memory1.Lock(0, 0); + EXPECT_EQ(base::DiscardableSharedMemory::FAILED, lock_rv); + lock_rv = memory2.Lock(0, 0); + EXPECT_EQ(base::DiscardableSharedMemory::SUCCESS, lock_rv); } TEST_F(HostDiscardableSharedMemoryManagerTest, EnforceMemoryPolicy) { @@ -181,7 +181,7 @@ // Memory policy should have successfully been enforced. EXPECT_FALSE(manager_->enforce_memory_policy_pending()); - EXPECT_FALSE(memory.Lock(0, 0)); + EXPECT_EQ(base::DiscardableSharedMemory::FAILED, memory.Lock(0, 0)); } } // namespace
diff --git a/content/common/mojo/service_registry_impl.h b/content/common/mojo/service_registry_impl.h index b3a6576..16426c7 100644 --- a/content/common/mojo/service_registry_impl.h +++ b/content/common/mojo/service_registry_impl.h
@@ -14,9 +14,9 @@ #include "base/compiler_specific.h" #include "base/memory/weak_ptr.h" #include "content/public/common/service_registry.h" -#include "mojo/public/cpp/bindings/interface_impl.h" -#include "mojo/public/cpp/system/core.h" -#include "mojo/public/interfaces/application/service_provider.mojom.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_impl.h" +#include "third_party/mojo/src/mojo/public/cpp/system/core.h" +#include "third_party/mojo/src/mojo/public/interfaces/application/service_provider.mojom.h" namespace content {
diff --git a/content/common/navigation_params.cc b/content/common/navigation_params.cc index 31787acb..63e6908 100644 --- a/content/common/navigation_params.cc +++ b/content/common/navigation_params.cc
@@ -10,22 +10,28 @@ CommonNavigationParams::CommonNavigationParams() : transition(ui::PAGE_TRANSITION_LINK), navigation_type(FrameMsg_Navigate_Type::NORMAL), - allow_download(true) { + allow_download(true), + report_type(FrameMsg_UILoadMetricsReportType::NO_REPORT) { } -CommonNavigationParams::~CommonNavigationParams() {} - CommonNavigationParams::CommonNavigationParams( const GURL& url, const Referrer& referrer, ui::PageTransition transition, FrameMsg_Navigate_Type::Value navigation_type, - bool allow_download) + bool allow_download, + base::TimeTicks ui_timestamp, + FrameMsg_UILoadMetricsReportType::Value report_type) : url(url), referrer(referrer), transition(transition), navigation_type(navigation_type), - allow_download(allow_download) { + allow_download(allow_download), + ui_timestamp(ui_timestamp), + report_type(report_type) { +} + +CommonNavigationParams::~CommonNavigationParams() { } RequestNavigationParams::RequestNavigationParams() : is_post(false) {}
diff --git a/content/common/navigation_params.h b/content/common/navigation_params.h index d30d3823..b23847c 100644 --- a/content/common/navigation_params.h +++ b/content/common/navigation_params.h
@@ -36,7 +36,9 @@ const Referrer& referrer, ui::PageTransition transition, FrameMsg_Navigate_Type::Value navigation_type, - bool allow_download); + bool allow_download, + base::TimeTicks ui_timestamp, + FrameMsg_UILoadMetricsReportType::Value report_type); ~CommonNavigationParams(); // The URL to navigate to. @@ -56,6 +58,14 @@ // Allows the URL to be downloaded (true by default). // Avoid downloading when in view-source mode. bool allow_download; + + // Timestamp of the user input event that triggered this navigation. Empty if + // the navigation was not triggered by clicking on a link or by receiving an + // intent on Android. + base::TimeTicks ui_timestamp; + + // The report type to be used when recording the metric using |ui_timestamp|. + FrameMsg_UILoadMetricsReportType::Value report_type; }; // Used by FrameMsg_Navigate.
diff --git a/content/common/navigator_connect_messages.h b/content/common/navigator_connect_messages.h index 5871bb4..4da29009 100644 --- a/content/common/navigator_connect_messages.h +++ b/content/common/navigator_connect_messages.h
@@ -4,13 +4,13 @@ // IPC messages for navigator.connect -#include "content/common/navigator_connect_types.h" +#include "content/public/common/navigator_connect_client.h" #include "ipc/ipc_message_macros.h" #include "url/gurl.h" #define IPC_MESSAGE_START NavigatorConnectMsgStart -IPC_STRUCT_TRAITS_BEGIN(content::CrossOriginServiceWorkerClient) +IPC_STRUCT_TRAITS_BEGIN(content::NavigatorConnectClient) IPC_STRUCT_TRAITS_MEMBER(target_url) IPC_STRUCT_TRAITS_MEMBER(origin) IPC_STRUCT_TRAITS_MEMBER(message_port_id) @@ -20,7 +20,7 @@ IPC_MESSAGE_CONTROL3(NavigatorConnectHostMsg_Connect, int /* thread_id */, int /* request_id */, - content::CrossOriginServiceWorkerClient /* client */) + content::NavigatorConnectClient /* client */) // Messages sent from the browser to the child process. IPC_MESSAGE_CONTROL3(NavigatorConnectMsg_ConnectResult,
diff --git a/content/common/navigator_connect_types.cc b/content/common/navigator_connect_types.cc deleted file mode 100644 index c0e5e6e..0000000 --- a/content/common/navigator_connect_types.cc +++ /dev/null
@@ -1,23 +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 "content/common/navigator_connect_types.h" - -namespace content { - -CrossOriginServiceWorkerClient::CrossOriginServiceWorkerClient() - : message_port_id(-1) { -} - -CrossOriginServiceWorkerClient::CrossOriginServiceWorkerClient( - const GURL& target_url, - const GURL& origin, - int message_port_id) - : target_url(target_url), origin(origin), message_port_id(message_port_id) { -} - -CrossOriginServiceWorkerClient::~CrossOriginServiceWorkerClient() { -} - -} // namespace content
diff --git a/content/common/navigator_connect_types.h b/content/common/navigator_connect_types.h deleted file mode 100644 index fe6ad82..0000000 --- a/content/common/navigator_connect_types.h +++ /dev/null
@@ -1,29 +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 CONTENT_COMMON_NAVIGATOR_CONNECT_TYPES_H_ -#define CONTENT_COMMON_NAVIGATOR_CONNECT_TYPES_H_ - -#include "url/gurl.h" - -// This file is to have common definitions that are to be shared by -// browser and child process. - -namespace content { - -struct CrossOriginServiceWorkerClient { - CrossOriginServiceWorkerClient(); - CrossOriginServiceWorkerClient(const GURL& target_url, - const GURL& origin, - int message_port_id); - ~CrossOriginServiceWorkerClient(); - - GURL target_url; - GURL origin; - int message_port_id; -}; - -} // namespace content - -#endif // CONTENT_COMMON_NAVIGATOR_CONNECT_TYPES_H_
diff --git a/content/common/render_frame_setup.mojom b/content/common/render_frame_setup.mojom index 0a1d433..22f01ea 100644 --- a/content/common/render_frame_setup.mojom +++ b/content/common/render_frame_setup.mojom
@@ -4,7 +4,7 @@ module content; -import "mojo/public/interfaces/application/service_provider.mojom"; +import "third_party/mojo/src/mojo/public/interfaces/application/service_provider.mojom"; interface RenderFrameSetup { GetServiceProviderForFrame(int32 frame_routing_id,
diff --git a/content/common/service_worker/service_worker_messages.h b/content/common/service_worker/service_worker_messages.h index 1a5c208..20b13ec 100644 --- a/content/common/service_worker/service_worker_messages.h +++ b/content/common/service_worker/service_worker_messages.h
@@ -8,9 +8,9 @@ #include <vector> #include "base/strings/string16.h" -#include "content/common/navigator_connect_types.h" #include "content/common/service_worker/service_worker_status_code.h" #include "content/common/service_worker/service_worker_types.h" +#include "content/public/common/navigator_connect_client.h" #include "content/public/common/platform_notification_data.h" #include "ipc/ipc_message_macros.h" #include "ipc/ipc_param_traits.h" @@ -299,6 +299,14 @@ // extract it and dispatch the message to the correct ServiceWorkerDispatcher // on the correct thread. +// Informs the child process of the registration associated with the service +// worker. +IPC_MESSAGE_CONTROL4(ServiceWorkerMsg_AssociateRegistrationWithServiceWorker, + int /* thread_id*/, + int /* provider_id */, + content::ServiceWorkerRegistrationObjectInfo, + content::ServiceWorkerVersionAttributes) + // Informs the child process that the given provider gets associated or // disassociated with the registration. IPC_MESSAGE_CONTROL4(ServiceWorkerMsg_AssociateRegistration, @@ -422,13 +430,13 @@ blink::WebCircularGeofencingRegion /* region */) IPC_MESSAGE_CONTROL2(ServiceWorkerMsg_CrossOriginConnectEvent, int /* request_id */, - content::CrossOriginServiceWorkerClient /* client */) + content::NavigatorConnectClient /* client */) IPC_MESSAGE_CONTROL3(ServiceWorkerMsg_MessageToWorker, base::string16 /* message */, std::vector<int> /* sent_message_port_ids */, std::vector<int> /* new_routing_ids */) IPC_MESSAGE_CONTROL4(ServiceWorkerMsg_CrossOriginMessageToWorker, - content::CrossOriginServiceWorkerClient /* client */, + content::NavigatorConnectClient /* client */, base::string16 /* message */, std::vector<int> /* sent_message_port_ids */, std::vector<int> /* new_routing_ids */)
diff --git a/content/common/service_worker/service_worker_types.cc b/content/common/service_worker/service_worker_types.cc index 52caf1f..2f371e6 100644 --- a/content/common/service_worker/service_worker_types.cc +++ b/content/common/service_worker/service_worker_types.cc
@@ -28,7 +28,7 @@ const GURL& url, const std::string& method, const ServiceWorkerHeaderMap& headers, - const GURL& referrer, + const Referrer& referrer, bool is_reload) : mode(FETCH_REQUEST_MODE_NO_CORS), request_context_type(REQUEST_CONTEXT_TYPE_UNSPECIFIED),
diff --git a/content/common/service_worker/service_worker_types.h b/content/common/service_worker/service_worker_types.h index 1af1bf0..6191a47 100644 --- a/content/common/service_worker/service_worker_types.h +++ b/content/common/service_worker/service_worker_types.h
@@ -11,6 +11,7 @@ #include "base/basictypes.h" #include "base/strings/string_util.h" #include "content/common/content_export.h" +#include "content/public/common/referrer.h" #include "content/public/common/request_context_frame_type.h" #include "content/public/common/request_context_type.h" #include "third_party/WebKit/public/platform/WebPageVisibilityState.h" @@ -87,7 +88,7 @@ ServiceWorkerFetchRequest(const GURL& url, const std::string& method, const ServiceWorkerHeaderMap& headers, - const GURL& referrer, + const Referrer& referrer, bool is_reload); ~ServiceWorkerFetchRequest(); @@ -99,7 +100,7 @@ ServiceWorkerHeaderMap headers; std::string blob_uuid; uint64 blob_size; - GURL referrer; + Referrer referrer; FetchCredentialsMode credentials_mode; bool is_reload; };
diff --git a/content/content_browser.gypi b/content/content_browser.gypi index 9fc7832..018b711 100644 --- a/content/content_browser.gypi +++ b/content/content_browser.gypi
@@ -150,6 +150,7 @@ 'public/browser/media_device_id.cc', 'public/browser/media_device_id.h', 'public/browser/memory_pressure_observer.h', + 'public/browser/message_port_delegate.h', 'public/browser/message_port_provider.h', 'public/browser/native_web_keyboard_event.h', 'public/browser/navigation_controller.cc', @@ -158,6 +159,8 @@ 'public/browser/navigation_details.h', 'public/browser/navigation_entry.h', 'public/browser/navigation_type.h', + 'public/browser/navigator_connect_context.h', + 'public/browser/navigator_connect_service_factory.h', 'public/browser/notification_details.h', 'public/browser/notification_event_dispatcher.h', 'public/browser/notification_observer.h', @@ -935,7 +938,6 @@ 'browser/media/webrtc_identity_store_backend.h', 'browser/manifest/manifest_manager_host.cc', 'browser/manifest/manifest_manager_host.h', - 'browser/message_port_delegate.h', 'browser/message_port_message_filter.cc', 'browser/message_port_message_filter.h', 'browser/message_port_provider.cc', @@ -949,10 +951,14 @@ 'browser/mojo/service_registrar_android.h', 'browser/mojo/service_registry_android.cc', 'browser/mojo/service_registry_android.h', - 'browser/navigator_connect/navigator_connect_context.cc', - 'browser/navigator_connect/navigator_connect_context.h', + 'browser/navigator_connect/navigator_connect_context_impl.cc', + 'browser/navigator_connect/navigator_connect_context_impl.h', 'browser/navigator_connect/navigator_connect_dispatcher_host.cc', 'browser/navigator_connect/navigator_connect_dispatcher_host.h', + 'browser/navigator_connect/navigator_connect_service.h', + 'browser/navigator_connect/navigator_connect_service_factory.h', + 'browser/navigator_connect/navigator_connect_service_worker_service_factory.cc', + 'browser/navigator_connect/navigator_connect_service_worker_service_factory.h', 'browser/net/browser_online_state_observer.cc', 'browser/net/browser_online_state_observer.h', 'browser/net/sqlite_persistent_cookie_store.cc', @@ -1023,6 +1029,8 @@ 'browser/renderer_host/file_utilities_message_filter.h', 'browser/renderer_host/font_utils_linux.cc', 'browser/renderer_host/font_utils_linux.h', + 'browser/renderer_host/frame_metadata_util.cc', + 'browser/renderer_host/frame_metadata_util.h', 'browser/renderer_host/gamepad_browser_message_filter.cc', 'browser/renderer_host/gamepad_browser_message_filter.h', 'browser/renderer_host/gpu_message_filter.cc',
diff --git a/content/content_common.gypi b/content/content_common.gypi index 87db959..2f712e4 100644 --- a/content/content_common.gypi +++ b/content/content_common.gypi
@@ -82,6 +82,8 @@ 'public/common/media_stream_request.h', 'public/common/menu_item.cc', 'public/common/menu_item.h', + 'public/common/navigator_connect_client.cc', + 'public/common/navigator_connect_client.h', 'public/common/page_state.cc', 'public/common/page_state.h', 'public/common/page_type.h', @@ -417,8 +419,6 @@ 'common/navigation_params.cc', 'common/navigation_params.h', 'common/navigator_connect_messages.h', - 'common/navigator_connect_types.cc', - 'common/navigator_connect_types.h', 'common/net/url_fetcher.cc', 'common/net/url_request_user_data.cc', 'common/net/url_request_user_data.h',
diff --git a/content/content_renderer.gypi b/content/content_renderer.gypi index 907cc10..9719042 100644 --- a/content/content_renderer.gypi +++ b/content/content_renderer.gypi
@@ -78,7 +78,6 @@ 'public/renderer/video_encode_accelerator.h', ], 'public_renderer_plugin_sources': [ - 'public/renderer/plugin_instance_throttler.cc', 'public/renderer/plugin_instance_throttler.h', ], 'private_renderer_sources': [ @@ -356,6 +355,8 @@ 'renderer/sad_plugin.h', 'renderer/savable_resources.cc', 'renderer/savable_resources.h', + 'renderer/scheduler/cancelable_closure_holder.cc', + 'renderer/scheduler/cancelable_closure_holder.h', 'renderer/scheduler/null_renderer_scheduler.cc', 'renderer/scheduler/null_renderer_scheduler.h', 'renderer/scheduler/renderer_scheduler.cc',
diff --git a/content/content_tests.gypi b/content/content_tests.gypi index e8c7528..17afeca 100644 --- a/content/content_tests.gypi +++ b/content/content_tests.gypi
@@ -205,6 +205,7 @@ 'browser/download/save_package_browsertest.cc', 'browser/fileapi/file_system_browsertest.cc', 'browser/frame_host/frame_tree_browsertest.cc', + 'browser/frame_host/render_frame_host_impl_browsertest.cc', 'browser/frame_host/render_frame_host_manager_browsertest.cc', 'browser/frame_host/navigation_controller_impl_browsertest.cc', 'browser/gpu/gpu_ipc_browsertests.cc', @@ -218,6 +219,7 @@ 'browser/media/media_browsertest.h', 'browser/media/media_canplaytype_browsertest.cc', 'browser/media/media_source_browsertest.cc', + 'browser/message_port_provider_browsertest.cc', 'browser/net_info_browsertest.cc', 'browser/plugin_browsertest.cc', 'browser/renderer_host/input/touch_action_browsertest.cc', @@ -332,6 +334,7 @@ 'browser/child_process_security_policy_unittest.cc', 'browser/cocoa/system_hotkey_map_unittest.mm', 'browser/compositor/buffer_queue_unittest.cc', + 'browser/compositor/reflector_impl_unittest.cc', 'browser/compositor/software_browser_compositor_output_surface_unittest.cc', 'browser/compositor/software_output_device_ozone_unittest.cc', 'browser/databases_table_unittest.cc', @@ -531,6 +534,7 @@ 'browser/service_worker/service_worker_utils_unittest.cc', 'browser/service_worker/service_worker_version_unittest.cc', 'browser/service_worker/service_worker_write_to_cache_job_unittest.cc', + 'browser/shareable_file_reference_unittest.cc', 'browser/shared_worker/shared_worker_instance_unittest.cc', 'browser/shared_worker/shared_worker_service_impl_unittest.cc', 'browser/site_instance_impl_unittest.cc', @@ -614,7 +618,6 @@ 'common/sandbox_mac_system_access_unittest.mm', 'common/sandbox_mac_unittest_helper.h', 'common/sandbox_mac_unittest_helper.mm', - 'common/shareable_file_reference_unittest.cc', 'common/webplugininfo_unittest.cc', 'renderer/android/email_detector_unittest.cc', 'renderer/android/phone_number_detector_unittest.cc',
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentViewRenderView.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewRenderView.java index a3093989..4bac354 100644 --- a/content/public/android/java/src/org/chromium/content/browser/ContentViewRenderView.java +++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewRenderView.java
@@ -190,14 +190,6 @@ nativeSetOverlayVideoMode(mNativeContentViewRenderView, enabled); } - /** - * Set the native layer tree helper for this {@link ContentViewRenderView}. - * @param layerTreeBuildHelperNativePtr Native pointer to the layer tree build helper. - */ - public void setLayerTreeBuildHelper(long layerTreeBuildHelperNativePtr) { - nativeSetLayerTreeBuildHelper(mNativeContentViewRenderView, layerTreeBuildHelperNativePtr); - } - @CalledByNative protected void onCompositorLayout() { } @@ -225,8 +217,6 @@ private native void nativeDestroy(long nativeContentViewRenderView); private native void nativeSetCurrentContentViewCore(long nativeContentViewRenderView, long nativeContentViewCore); - private native void nativeSetLayerTreeBuildHelper(long nativeContentViewRenderView, - long buildHelperNativePtr); private native void nativeSurfaceCreated(long nativeContentViewRenderView); private native void nativeSurfaceDestroyed(long nativeContentViewRenderView); private native void nativeSurfaceChanged(long nativeContentViewRenderView,
diff --git a/content/public/android/java/src/org/chromium/content_public/browser/LoadUrlParams.java b/content/public/android/java/src/org/chromium/content_public/browser/LoadUrlParams.java index d65d757..bc8f15b 100644 --- a/content/public/android/java/src/org/chromium/content_public/browser/LoadUrlParams.java +++ b/content/public/android/java/src/org/chromium/content_public/browser/LoadUrlParams.java
@@ -21,12 +21,6 @@ */ @JNINamespace("content") public class LoadUrlParams { - // These fields have been replaced by build-time generated enums and should be removed when - // no longer used downstream. - @Deprecated - public static final int LOAD_TYPE_BROWSER_INITIATED_HTTP_POST = - LoadURLType.BROWSER_INITIATED_HTTP_POST; - // Fields with counterparts in NavigationController::LoadURLParams. // Package private so that ContentViewCore.loadUrl can pass them down to // native code. Should not be accessed directly anywhere else outside of @@ -43,6 +37,7 @@ String mVirtualUrlForDataUrl; boolean mCanLoadLocalResources; boolean mIsRendererInitiated; + long mIntentReceivedTimestamp; /** * Creates an instance with default page transition type. @@ -396,6 +391,21 @@ return mIsRendererInitiated; } + /** + * @param intentReceivedTimestamp the timestamp at which Chrome received the intent that + * triggered this URL load, as returned by System.currentMillis. + */ + public void setIntentReceivedTimestamp(long intentReceivedTimestamp) { + mIntentReceivedTimestamp = intentReceivedTimestamp; + } + + /** + * @return The timestamp at which Chrome received the intent that triggered this URL load. + */ + public long getIntentReceivedTimestamp() { + return mIntentReceivedTimestamp; + } + public boolean isBaseUrlDataScheme() { // If there's no base url set, but this is a data load then // treat the scheme as data:.
diff --git a/content/public/browser/android/layer_tree_build_helper.h b/content/public/browser/android/layer_tree_build_helper.h deleted file mode 100644 index 4f23a4b..0000000 --- a/content/public/browser/android/layer_tree_build_helper.h +++ /dev/null
@@ -1,31 +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 CONTENT_PUBLIC_BROWSER_ANDROID_LAYER_TREE_BUILD_HELPER_H_ -#define CONTENT_PUBLIC_BROWSER_ANDROID_LAYER_TREE_BUILD_HELPER_H_ - -#include "base/memory/ref_counted.h" - -namespace cc { -class Layer; -} - -namespace content { - -// A Helper class to build a layer tree to be composited -// given a content root layer. -class LayerTreeBuildHelper { - public: - LayerTreeBuildHelper() {}; - virtual scoped_refptr<cc::Layer> GetLayerTree( - scoped_refptr<cc::Layer> content_root_layer) = 0; - virtual ~LayerTreeBuildHelper() {}; - - private: - DISALLOW_COPY_AND_ASSIGN(LayerTreeBuildHelper); -}; - -} - -#endif // CONTENT_PUBLIC_BROWSER_ANDROID_LAYER_TREE_BUILD_HELPER_H_
diff --git a/content/public/browser/browser_message_filter.h b/content/public/browser/browser_message_filter.h index 00cff67..1966e584 100644 --- a/content/public/browser/browser_message_filter.h +++ b/content/public/browser/browser_message_filter.h
@@ -81,7 +81,7 @@ base::ProcessHandle PeerHandle(); // Can be called on any thread, after OnChannelConnected is called. - base::ProcessId peer_pid() const { return peer_process_.pid(); } + base::ProcessId peer_pid() const { return peer_process_.Pid(); } void set_peer_process_for_testing(base::Process peer_process) { peer_process_ = peer_process.Pass();
diff --git a/content/public/browser/browser_plugin_guest_delegate.h b/content/public/browser/browser_plugin_guest_delegate.h index 8c8a10c..5e5d1fe 100644 --- a/content/public/browser/browser_plugin_guest_delegate.h +++ b/content/public/browser/browser_plugin_guest_delegate.h
@@ -58,10 +58,9 @@ virtual WebContents* GetOwnerWebContents() const; // Notifies that the content size of the guest has changed. - // Note: In autosize mode, it si possible that the guest size may not match + // Note: In autosize mode, it is possible that the guest size may not match // the element size. - virtual void GuestSizeChanged(const gfx::Size& old_size, - const gfx::Size& new_size) {} + virtual void GuestSizeChanged(const gfx::Size& new_size) {} // Asks the delegate if the given guest can lock the pointer. // Invoking the |callback| synchronously is OK.
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h index e5f40c4..39acf3d 100644 --- a/content/public/browser/content_browser_client.h +++ b/content/public/browser/content_browser_client.h
@@ -92,6 +92,8 @@ class ExternalVideoSurfaceContainer; class LocationProvider; class MediaObserver; +class NavigatorConnectContext; +class NavigatorConnectServiceFactory; class PlatformNotificationService; class QuotaPermissionContext; class RenderFrameHost; @@ -588,6 +590,11 @@ // RenderProcessHost. virtual void OverrideRenderProcessMojoServices(ServiceRegistry* registry) {} + // Registers additional navigator.connect service factories available in a + // particular NavigatorConnectContext. + virtual void GetAdditionalNavigatorConnectServices( + const scoped_refptr<NavigatorConnectContext>& context) {} + #if defined(OS_POSIX) && !defined(OS_MACOSX) // Populates |mappings| with all files that need to be mapped before launching // a child process.
diff --git a/content/browser/message_port_delegate.h b/content/public/browser/message_port_delegate.h similarity index 76% rename from content/browser/message_port_delegate.h rename to content/public/browser/message_port_delegate.h index 8f6ad1b..70abbeb2 100644 --- a/content/browser/message_port_delegate.h +++ b/content/public/browser/message_port_delegate.h
@@ -2,12 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_BROWSER_MESSAGE_PORT_DELEGATE_H_ -#define CONTENT_BROWSER_MESSAGE_PORT_DELEGATE_H_ +#ifndef CONTENT_PUBLIC_BROWSER_MESSAGE_PORT_DELEGATE_H_ +#define CONTENT_PUBLIC_BROWSER_MESSAGE_PORT_DELEGATE_H_ #include <vector> #include "base/strings/string16.h" +#include "content/common/content_export.h" namespace content { @@ -15,7 +16,7 @@ // correct renderer. Delegates are responsible for managing their own lifetime, // and should call MessagePortService::OnMessagePortDelegateClosing if they are // destroyed while there are still message ports associated with them. -class MessagePortDelegate { +class CONTENT_EXPORT MessagePortDelegate { public: // Sends a message to the given route. Implementations are responsible for // updating MessagePortService with new routes for the sent message ports. @@ -23,7 +24,7 @@ const base::string16& message, const std::vector<int>& sent_message_port_ids) = 0; - // Sends a "messages are queued" IPC to the given route. + // Requests messages to the given route to be queued. virtual void SendMessagesAreQueued(int route_id) = 0; protected: @@ -32,4 +33,4 @@ } // namespace content -#endif // CONTENT_BROWSER_MESSAGE_PORT_DELEGATE_H_ +#endif // CONTENT_PUBLIC_BROWSER_MESSAGE_PORT_DELEGATE_H_
diff --git a/content/public/browser/message_port_provider.h b/content/public/browser/message_port_provider.h index aab9269..70fbe11 100644 --- a/content/public/browser/message_port_provider.h +++ b/content/public/browser/message_port_provider.h
@@ -1,4 +1,4 @@ -// Copyright (c) 2014 The Chromium Authors. All rights reserved. +// 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. @@ -14,6 +14,7 @@ namespace content { +class MessagePortDelegate; class WebContents; // An interface consisting of methods that can be called to use Message ports. @@ -24,7 +25,7 @@ // part of the message. // See https://html.spec.whatwg.org/multipage/comms.html#messageevent for // further information on message events. - // Should be called on IO thread. + // Should be called on UI thread. static void PostMessageToFrame(WebContents* web_contents, const base::string16& source_origin, const base::string16& target_origin, @@ -35,10 +36,15 @@ // associated with this message channel. // See https://html.spec.whatwg.org/multipage/comms.html#messagechannel // Should be called on IO thread. - static void CreateMessageChannel(WebContents* web_contents, + // The message ports that are created will have their routing id numbers equal + // to the message port numbers. + static void CreateMessageChannel(MessagePortDelegate* delegate, int* port1, int* port2); + // Cleanup the message ports that belong to the closing delegate. + static void OnMessagePortDelegateClosing(MessagePortDelegate * delegate); + private: DISALLOW_IMPLICIT_CONSTRUCTORS(MessagePortProvider); };
diff --git a/content/public/browser/navigation_controller.cc b/content/public/browser/navigation_controller.cc index b2bb686..23b32d9 100644 --- a/content/public/browser/navigation_controller.cc +++ b/content/public/browser/navigation_controller.cc
@@ -18,7 +18,10 @@ browser_initiated_post_data(nullptr), can_load_local_resources(false), should_replace_current_entry(false), - should_clear_history_list(false) { + should_clear_history_list(false) { +#if defined(OS_ANDROID) + intent_received_timestamp = 0; +#endif } NavigationController::LoadURLParams::~LoadURLParams() { @@ -40,6 +43,9 @@ browser_initiated_post_data(other.browser_initiated_post_data), should_replace_current_entry(false), should_clear_history_list(false) { +#if defined(OS_ANDROID) + intent_received_timestamp = other.intent_received_timestamp; +#endif } NavigationController::LoadURLParams& @@ -60,6 +66,9 @@ browser_initiated_post_data = other.browser_initiated_post_data; should_replace_current_entry = other.should_replace_current_entry; should_clear_history_list = other.should_clear_history_list; +#if defined(OS_ANDROID) + intent_received_timestamp = other.intent_received_timestamp; +#endif return *this; }
diff --git a/content/public/browser/navigation_controller.h b/content/public/browser/navigation_controller.h index c02f38f..7d201e54 100644 --- a/content/public/browser/navigation_controller.h +++ b/content/public/browser/navigation_controller.h
@@ -184,6 +184,13 @@ // commits. bool should_clear_history_list; +#if defined(OS_ANDROID) + // On Android, for a load triggered by an intent, the time Chrome received + // the original intent that prompted the load (in milliseconds active time + // since boot). + int64 intent_received_timestamp; +#endif + explicit LoadURLParams(const GURL& url); ~LoadURLParams();
diff --git a/content/public/browser/navigator_connect_context.h b/content/public/browser/navigator_connect_context.h new file mode 100644 index 0000000..083892b --- /dev/null +++ b/content/public/browser/navigator_connect_context.h
@@ -0,0 +1,36 @@ +// 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 CONTENT_PUBLIC_BROWSER_NAVIGATOR_CONNECT_CONTEXT_H_ +#define CONTENT_PUBLIC_BROWSER_NAVIGATOR_CONNECT_CONTEXT_H_ + +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" + +namespace content { + +class NavigatorConnectServiceFactory; + +// Use this class to register additional navigator.connect service factories. +// One instance of this class exists per StoragePartition. +// TODO(mek): Add API to this class so NavigatorConnectService implementations +// can send messages back to the client. +// TODO(mek): Add API so services can close a connection. +class NavigatorConnectContext + : public base::RefCountedThreadSafe<NavigatorConnectContext> { + public: + // Register a service factory. The most recently added factory that claims to + // handle a URL will be used to handle a connection request for that URL. + virtual void AddFactory( + scoped_ptr<NavigatorConnectServiceFactory> factory) = 0; + + protected: + friend class base::RefCountedThreadSafe<NavigatorConnectContext>; + NavigatorConnectContext() {} + virtual ~NavigatorConnectContext() {} +}; + +} // namespace content + +#endif // CONTENT_PUBLIC_BROWSER_NAVIGATOR_CONNECT_CONTEXT_H_
diff --git a/content/public/browser/navigator_connect_service_factory.h b/content/public/browser/navigator_connect_service_factory.h new file mode 100644 index 0000000..f66b2de --- /dev/null +++ b/content/public/browser/navigator_connect_service_factory.h
@@ -0,0 +1,45 @@ +// Copyright 2015 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_PUBLIC_BROWSER_NAVIGATOR_CONNECT_SERVICE_FACTORY_H_ +#define CONTENT_PUBLIC_BROWSER_NAVIGATOR_CONNECT_SERVICE_FACTORY_H_ + +#include "base/callback.h" + +class GURL; + +namespace content { + +struct NavigatorConnectClient; +class MessagePortDelegate; + +// Implement this interface to provide a new kind of navigator.connect +// accessible service. +// Instances of this class are owned by NavigatorConnectContext. Register new +// factories by calling NavigatorConnectContext::AddFactory. +class NavigatorConnectServiceFactory { + public: + // Call with nullptr to indicate connection failure. Ownership of the delegate + // remains with the factory. It is assumed that for the passed + // MessagePortDelegate implementation the route_id and message_port_id of a + // connection are the same. + using ConnectCallback = base::Callback<void(MessagePortDelegate*)>; + + virtual ~NavigatorConnectServiceFactory() {} + + // Return true if this factory is responsible for handling connections to the + // |target_url|. The most recently added factory that returns true for a + // particular url is picked to handle the connection attempt. + virtual bool HandlesUrl(const GURL& target_url) = 0; + + // Called to try to establish a connection. Only called if this factory was + // the most recently added factory that returned true from |HandlesUrl| for + // the url being connected to. + virtual void Connect(const NavigatorConnectClient& client, + const ConnectCallback& callback) = 0; +}; + +} // namespace content + +#endif // CONTENT_PUBLIC_BROWSER_NAVIGATOR_CONNECT_SERVICE_FACTORY_H_
diff --git a/content/public/browser/render_view_host.h b/content/public/browser/render_view_host.h index 5e79009e..07fc988 100644 --- a/content/public/browser/render_view_host.h +++ b/content/public/browser/render_view_host.h
@@ -12,8 +12,8 @@ #include "content/public/browser/render_widget_host.h" #include "content/public/common/file_chooser_params.h" #include "content/public/common/page_zoom.h" -#include "mojo/public/cpp/system/core.h" #include "third_party/WebKit/public/web/WebDragOperation.h" +#include "third_party/mojo/src/mojo/public/cpp/system/core.h" class GURL;
diff --git a/content/public/browser/web_contents_observer.h b/content/public/browser/web_contents_observer.h index dde8881..d981278 100644 --- a/content/public/browser/web_contents_observer.h +++ b/content/public/browser/web_contents_observer.h
@@ -118,7 +118,8 @@ // // DEPRECATED. This method is difficult to use correctly and should be // removed. TODO(creis): Remove in http://crbug.com/424641. - virtual void AboutToNavigateRenderFrame(RenderFrameHost* render_frame_host) {} + virtual void AboutToNavigateRenderFrame(RenderFrameHost* old_host, + RenderFrameHost* new_host) {} // This method is invoked after the browser process starts a navigation to a // pending NavigationEntry. It is not called for renderer-initiated
diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc index 830a7da..9a41cc6 100644 --- a/content/public/common/content_switches.cc +++ b/content/public/common/content_switches.cc
@@ -158,7 +158,6 @@ const char kDisableHistogramCustomizer[] = "disable-histogram-customizer"; // Paint content on the main thread instead of the compositor thread. -// Overrides the kEnableImplSidePainting flag. const char kDisableImplSidePainting[] = "disable-impl-side-painting"; // Prevent Java from running. @@ -312,8 +311,8 @@ // Enables restarting interrupted downloads. const char kEnableDownloadResumption[] = "enable-download-resumption"; -// Enables support for Encrypted Media Extensions (e.g. MediaKeys). -const char kEnableEncryptedMedia[] = "enable-encrypted-media"; +// Disables (unprefixed) Encrypted Media Extensions. +const char kDisableEncryptedMedia[] = "disable-encrypted-media"; // Enable experimental canvas features, e.g. canvas 2D context attributes const char kEnableExperimentalCanvasFeatures[] = @@ -342,9 +341,6 @@ // Dynamically apply color profiles to web content images. const char kEnableImageColorProfiles[] = "enable-image-color-profiles"; -// Paint content on the compositor thread instead of the main thread. -const char kEnableImplSidePainting[] = "enable-impl-side-painting"; - // Force logging to be enabled. Logging is disabled by default in release // builds. const char kEnableLogging[] = "enable-logging"; @@ -666,8 +662,8 @@ // Enables remote debug over HTTP on the specified port. const char kRemoteDebuggingPort[] = "remote-debugging-port"; -// On POSIX only: the contents of this flag are prepended to the renderer -// command line. Useful values might be "valgrind" or "xterm -e gdb --args". +// The contents of this flag are prepended to the renderer command line. +// Useful values might be "valgrind" or "xterm -e gdb --args". const char kRendererCmdPrefix[] = "renderer-cmd-prefix"; // Causes the process to run as renderer instead of as browser. @@ -820,9 +816,8 @@ // Use the new surfaces system to handle compositor delegation. const char kUseSurfaces[] = "use-surfaces"; -// On POSIX only: the contents of this flag are prepended to the utility -// process command line. Useful values might be "valgrind" or "xterm -e gdb -// --args". +// The contents of this flag are prepended to the utility process command line. +// Useful values might be "valgrind" or "xterm -e gdb --args". const char kUtilityCmdPrefix[] = "utility-cmd-prefix"; // Causes the process to run as a utility subprocess.
diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h index 6b72dbc5..5cd17459 100644 --- a/content/public/common/content_switches.h +++ b/content/public/common/content_switches.h
@@ -43,6 +43,7 @@ CONTENT_EXPORT extern const char kDisableDistanceFieldText[]; CONTENT_EXPORT extern const char kDisableDisplayList2dCanvas[]; extern const char kDisableDomainBlockingFor3DAPIs[]; +CONTENT_EXPORT extern const char kDisableEncryptedMedia[]; CONTENT_EXPORT extern const char kDisableExperimentalWebGL[]; CONTENT_EXPORT extern const char kDisableFileSystem[]; CONTENT_EXPORT extern const char kDisableFlash3d[]; @@ -96,7 +97,6 @@ CONTENT_EXPORT extern const char kEnableDisplayList2dCanvas[]; CONTENT_EXPORT extern const char kEnableDistanceFieldText[]; CONTENT_EXPORT extern const char kEnableDownloadResumption[]; -CONTENT_EXPORT extern const char kEnableEncryptedMedia[]; CONTENT_EXPORT extern const char kEnableExperimentalCanvasFeatures[]; CONTENT_EXPORT extern const char kEnableExperimentalWebPlatformFeatures[]; CONTENT_EXPORT extern const char kEnableFileCookies[]; @@ -104,7 +104,6 @@ CONTENT_EXPORT extern const char kEnableGpuRasterization[]; CONTENT_EXPORT extern const char kEnableLowResTiling[]; CONTENT_EXPORT extern const char kEnableImageColorProfiles[]; -CONTENT_EXPORT extern const char kEnableImplSidePainting[]; CONTENT_EXPORT extern const char kEnableLCDText[]; CONTENT_EXPORT extern const char kEnableLogging[]; extern const char kEnableMemoryBenchmarking[];
diff --git a/content/public/common/navigator_connect_client.cc b/content/public/common/navigator_connect_client.cc new file mode 100644 index 0000000..bf21bc9 --- /dev/null +++ b/content/public/common/navigator_connect_client.cc
@@ -0,0 +1,21 @@ +// 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 "content/public/common/navigator_connect_client.h" + +namespace content { + +NavigatorConnectClient::NavigatorConnectClient() : message_port_id(-1) { +} + +NavigatorConnectClient::NavigatorConnectClient(const GURL& target_url, + const GURL& origin, + int message_port_id) + : target_url(target_url), origin(origin), message_port_id(message_port_id) { +} + +NavigatorConnectClient::~NavigatorConnectClient() { +} + +} // namespace content
diff --git a/content/public/common/navigator_connect_client.h b/content/public/common/navigator_connect_client.h new file mode 100644 index 0000000..9cc66ec --- /dev/null +++ b/content/public/common/navigator_connect_client.h
@@ -0,0 +1,33 @@ +// 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 CONTENT_PUBLIC_COMMON_NAVIGATOR_CONNECT_CLIENT_H_ +#define CONTENT_PUBLIC_COMMON_NAVIGATOR_CONNECT_CLIENT_H_ + +#include "url/gurl.h" + +namespace content { + +// This struct represents a connection to a navigator.connect exposed service. +struct NavigatorConnectClient { + NavigatorConnectClient(); + NavigatorConnectClient(const GURL& target_url, + const GURL& origin, + int message_port_id); + ~NavigatorConnectClient(); + + // The URL this client is connected to (or trying to connect to). + GURL target_url; + + // The origin of the client. + GURL origin; + + // Message port ID for the service side message port associated with this + // client. + int message_port_id; +}; + +} // namespace content + +#endif // CONTENT_PUBLIC_COMMON_NAVIGATOR_CONNECT_CLIENT_H_
diff --git a/content/public/common/service_registry.h b/content/public/common/service_registry.h index be2294e..1ce3b03 100644 --- a/content/public/common/service_registry.h +++ b/content/public/common/service_registry.h
@@ -11,9 +11,9 @@ #include "base/callback.h" #include "base/strings/string_piece.h" #include "content/common/content_export.h" -#include "mojo/public/cpp/bindings/interface_ptr.h" -#include "mojo/public/cpp/bindings/interface_request.h" -#include "mojo/public/cpp/system/core.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_ptr.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h" +#include "third_party/mojo/src/mojo/public/cpp/system/core.h" namespace content {
diff --git a/content/public/renderer/plugin_instance_throttler.cc b/content/public/renderer/plugin_instance_throttler.cc deleted file mode 100644 index 8fde88a..0000000 --- a/content/public/renderer/plugin_instance_throttler.cc +++ /dev/null
@@ -1,26 +0,0 @@ -// Copyright 2015 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/public/renderer/plugin_instance_throttler.h" - -#include "content/renderer/pepper/plugin_instance_throttler_impl.h" - -namespace content { - -// static -scoped_ptr<PluginInstanceThrottler> PluginInstanceThrottler::Get( - RenderFrame* frame, - const GURL& plugin_url, - PluginPowerSaverMode power_saver_mode) { - if (power_saver_mode == PluginPowerSaverMode::POWER_SAVER_MODE_ESSENTIAL) - return nullptr; - - bool power_saver_enabled = - power_saver_mode == - PluginPowerSaverMode::POWER_SAVER_MODE_PERIPHERAL_THROTTLED; - return make_scoped_ptr( - new PluginInstanceThrottlerImpl(frame, plugin_url, power_saver_enabled)); -} - -} // namespace content
diff --git a/content/public/renderer/plugin_instance_throttler.h b/content/public/renderer/plugin_instance_throttler.h index 617b4b12..5fa32767 100644 --- a/content/public/renderer/plugin_instance_throttler.h +++ b/content/public/renderer/plugin_instance_throttler.h
@@ -70,6 +70,8 @@ const GURL& plugin_url, PluginPowerSaverMode power_saver_mode); + static void RecordUnthrottleMethodMetric(PowerSaverUnthrottleMethod method); + virtual ~PluginInstanceThrottler() {} virtual void AddObserver(Observer* observer) = 0;
diff --git a/content/public/renderer/render_frame_observer.h b/content/public/renderer/render_frame_observer.h index b806b0f1..f2c429b 100644 --- a/content/public/renderer/render_frame_observer.h +++ b/content/public/renderer/render_frame_observer.h
@@ -16,6 +16,7 @@ namespace blink { class WebFormElement; class WebFrame; +class WebNode; struct WebURLError; } @@ -85,6 +86,9 @@ // Called when a compositor frame has committed. virtual void DidCommitCompositorFrame() {} + // Called when the focused node has changed to |node|. + virtual void FocusedNodeChanged(const blink::WebNode& node) {} + // IPC::Listener implementation. bool OnMessageReceived(const IPC::Message& message) override;
diff --git a/content/public/test/browser_test_utils.cc b/content/public/test/browser_test_utils.cc index 89dd343..20d6f6c9 100644 --- a/content/public/test/browser_test_utils.cc +++ b/content/public/test/browser_test_utils.cc
@@ -723,6 +723,28 @@ loop_runner->Run(); } +bool WaitForRenderFrameReady(RenderFrameHost* rfh) { + if (!rfh) + return false; + std::string result; + EXPECT_TRUE( + content::ExecuteScriptAndExtractString( + rfh, + "(function() {" + " var done = false;" + " function checkState() {" + " if (!done && document.readyState == 'complete') {" + " done = true;" + " window.domAutomationController.send('pageLoadComplete');" + " }" + " }" + " checkState();" + " document.addEventListener('readystatechange', checkState);" + "})();", + &result)); + return result == "pageLoadComplete"; +} + TitleWatcher::TitleWatcher(WebContents* web_contents, const base::string16& expected_title) : WebContentsObserver(web_contents),
diff --git a/content/public/test/browser_test_utils.h b/content/public/test/browser_test_utils.h index 303ac74..a55ad06c 100644 --- a/content/public/test/browser_test_utils.h +++ b/content/public/test/browser_test_utils.h
@@ -243,6 +243,12 @@ void RunTaskAndWaitForInterstitialDetach(content::WebContents* web_contents, const base::Closure& task); +// Waits until all resources have loaded in the given RenderFrameHost. +// When the load completes, this function sends a "pageLoadComplete" message +// via domAutomationController. The caller should make sure this extra +// message is handled properly. +bool WaitForRenderFrameReady(RenderFrameHost* rfh) WARN_UNUSED_RESULT; + // Watches title changes on a WebContents, blocking until an expected title is // set. class TitleWatcher : public WebContentsObserver {
diff --git a/content/public/test/mock_blob_url_request_context.cc b/content/public/test/mock_blob_url_request_context.cc index 6ebaa655..6f55870 100644 --- a/content/public/test/mock_blob_url_request_context.cc +++ b/content/public/test/mock_blob_url_request_context.cc
@@ -4,11 +4,10 @@ #include "content/public/test/mock_blob_url_request_context.h" +#include "storage/browser/blob/blob_data_builder.h" #include "storage/browser/blob/blob_storage_context.h" #include "storage/browser/blob/blob_url_request_job.h" #include "storage/browser/blob/blob_url_request_job_factory.h" -#include "storage/common/blob/blob_data.h" - namespace content { @@ -35,10 +34,10 @@ : blob_id_(blob_id), context_(request_context.blob_storage_context()) { DCHECK(context_); - scoped_refptr<storage::BlobData> blob_data(new storage::BlobData(blob_id_)); + storage::BlobDataBuilder blob_builder(blob_id_); if (!data.empty()) - blob_data->AppendData(data); - handle_ = context_->AddFinishedBlob(blob_data.get()); + blob_builder.AppendData(data); + handle_ = context_->AddFinishedBlob(blob_builder); } ScopedTextBlob::~ScopedTextBlob() {
diff --git a/content/public/test/render_view_test.cc b/content/public/test/render_view_test.cc index 549dd9f..16aafda1 100644 --- a/content/public/test/render_view_test.cc +++ b/content/public/test/render_view_test.cc
@@ -343,7 +343,7 @@ void RenderViewTest::SetFocused(const blink::WebNode& node) { RenderViewImpl* impl = static_cast<RenderViewImpl*>(view_); - impl->focusedNodeChanged(node); + impl->focusedNodeChanged(blink::WebNode(), node); } void RenderViewTest::Reload(const GURL& url) {
diff --git a/content/renderer/accessibility/renderer_accessibility.cc b/content/renderer/accessibility/renderer_accessibility.cc index 8efdfd8..b8152ba 100644 --- a/content/renderer/accessibility/renderer_accessibility.cc +++ b/content/renderer/accessibility/renderer_accessibility.cc
@@ -108,7 +108,8 @@ Send(new AccessibilityHostMsg_FindInPageResult(routing_id(), params)); } -void RendererAccessibility::FocusedNodeChanged(const WebNode& node) { +void RendererAccessibility::AccessibilityFocusedNodeChanged( + const WebNode& node) { const WebDocument& document = GetMainDocument(); if (document.isNull()) return;
diff --git a/content/renderer/accessibility/renderer_accessibility.h b/content/renderer/accessibility/renderer_accessibility.h index 2c3d8e8..be0ca59 100644 --- a/content/renderer/accessibility/renderer_accessibility.h +++ b/content/renderer/accessibility/renderer_accessibility.h
@@ -65,7 +65,7 @@ const blink::WebAXObject& end_object, int end_offset); - void FocusedNodeChanged(const blink::WebNode& node); + void AccessibilityFocusedNodeChanged(const blink::WebNode& node); // This can be called before deleting a RendererAccessibility instance due // to the accessibility mode changing, as opposed to during frame destruction
diff --git a/content/renderer/devtools/devtools_agent.cc b/content/renderer/devtools/devtools_agent.cc index c84cecd..780001c 100644 --- a/content/renderer/devtools/devtools_agent.cc +++ b/content/renderer/devtools/devtools_agent.cc
@@ -118,21 +118,12 @@ return handled; } -void DevToolsAgent::sendMessageToInspectorFrontend( - const blink::WebString& message) { - std::string msg(message.utf8()); - if (msg.length() < kMaxMessageChunkSize) { - Send(new DevToolsClientMsg_DispatchOnInspectorFrontend( - routing_id(), msg, msg.size())); - return; - } - - for (size_t pos = 0; pos < msg.length(); pos += kMaxMessageChunkSize) { - Send(new DevToolsClientMsg_DispatchOnInspectorFrontend( - routing_id(), - msg.substr(pos, kMaxMessageChunkSize), - pos ? 0 : msg.size())); - } +void DevToolsAgent::sendProtocolMessage( + int call_id, + const blink::WebString& message, + const blink::WebString& state_cookie) { + SendChunkedProtocolMessage( + this, routing_id(), call_id, message.utf8(), state_cookie.utf8()); } long DevToolsAgent::processId() { @@ -143,11 +134,6 @@ return routing_id(); } -void DevToolsAgent::saveAgentRuntimeState( - const blink::WebString& state) { - Send(new DevToolsHostMsg_SaveAgentRuntimeState(routing_id(), state.utf8())); -} - blink::WebDevToolsAgentClient::WebKitClientMessageLoop* DevToolsAgent::createClientMessageLoop() { return new WebKitClientMessageLoopImpl(); @@ -275,6 +261,39 @@ return NULL; } +// static +void DevToolsAgent::SendChunkedProtocolMessage( + IPC::Sender* sender, + int routing_id, + int call_id, + const std::string& message, + const std::string& post_state) { + DevToolsMessageChunk chunk; + chunk.message_size = message.size(); + chunk.is_first = true; + + if (message.length() < kMaxMessageChunkSize) { + chunk.data = message; + chunk.call_id = call_id; + chunk.post_state = post_state; + chunk.is_last = true; + sender->Send(new DevToolsClientMsg_DispatchOnInspectorFrontend( + routing_id, chunk)); + return; + } + + for (size_t pos = 0; pos < message.length(); pos += kMaxMessageChunkSize) { + chunk.is_last = pos + kMaxMessageChunkSize >= message.length(); + chunk.call_id = chunk.is_last ? call_id : 0; + chunk.post_state = chunk.is_last ? post_state : std::string(); + chunk.data = message.substr(pos, kMaxMessageChunkSize); + sender->Send(new DevToolsClientMsg_DispatchOnInspectorFrontend( + routing_id, chunk)); + chunk.is_first = false; + chunk.message_size = 0; + } +} + void DevToolsAgent::OnAttach(const std::string& host_id) { WebDevToolsAgent* web_agent = GetWebAgent(); if (web_agent) {
diff --git a/content/renderer/devtools/devtools_agent.h b/content/renderer/devtools/devtools_agent.h index 8a8d998..5140a43 100644 --- a/content/renderer/devtools/devtools_agent.h +++ b/content/renderer/devtools/devtools_agent.h
@@ -40,6 +40,13 @@ // Returns agent instance for its routing id. static DevToolsAgent* FromRoutingId(int routing_id); + static void SendChunkedProtocolMessage( + IPC::Sender* sender, + int routing_id, + int call_id, + const std::string& message, + const std::string& post_state); + blink::WebDevToolsAgent* GetWebAgent(); bool IsAttached(); @@ -49,32 +56,32 @@ bool OnMessageReceived(const IPC::Message& message) override; // WebDevToolsAgentClient implementation - virtual void sendMessageToInspectorFrontend(const blink::WebString& data); - - virtual long processId() override; - virtual int debuggerId() override; - virtual void saveAgentRuntimeState(const blink::WebString& state) override; - virtual blink::WebDevToolsAgentClient::WebKitClientMessageLoop* + void sendProtocolMessage(int call_id, + const blink::WebString& response, + const blink::WebString& state) override; + long processId() override; + int debuggerId() override; + blink::WebDevToolsAgentClient::WebKitClientMessageLoop* createClientMessageLoop() override; - virtual void willEnterDebugLoop() override; - virtual void didExitDebugLoop() override; + void willEnterDebugLoop() override; + void didExitDebugLoop() override; typedef void (*TraceEventCallback)( char phase, const unsigned char*, const char* name, unsigned long long id, int numArgs, const char* const* argNames, const unsigned char* argTypes, const unsigned long long* argValues, unsigned char flags, double timestamp); - virtual void resetTraceEventCallback() override; - virtual void setTraceEventCallback(const blink::WebString& category_filter, - TraceEventCallback cb) override; - virtual void enableTracing(const blink::WebString& category_filter) override; - virtual void disableTracing() override; - virtual void startGPUEventsRecording() override; - virtual void stopGPUEventsRecording() override; + void resetTraceEventCallback() override; + void setTraceEventCallback(const blink::WebString& category_filter, + TraceEventCallback cb) override; + void enableTracing(const blink::WebString& category_filter) override; + void disableTracing() override; + void startGPUEventsRecording() override; + void stopGPUEventsRecording() override; - virtual void enableDeviceEmulation( + void enableDeviceEmulation( const blink::WebDeviceEmulationParams& params) override; - virtual void disableDeviceEmulation() override; + void disableDeviceEmulation() override; void OnAttach(const std::string& host_id); void OnReattach(const std::string& host_id,
diff --git a/content/renderer/input/input_handler_proxy.cc b/content/renderer/input/input_handler_proxy.cc index c62d489..913ae00 100644 --- a/content/renderer/input/input_handler_proxy.cc +++ b/content/renderer/input/input_handler_proxy.cc
@@ -132,7 +132,7 @@ if (it == latency_info.latency_components.end()) return; - base::TimeDelta delta = base::TimeTicks::HighResNow() - it->second.event_time; + base::TimeDelta delta = base::TimeTicks::Now() - it->second.event_time; for (size_t i = 0; i < it->second.event_count; ++i) { switch (event.type) { case blink::WebInputEvent::GestureScrollBegin: @@ -186,8 +186,7 @@ disallow_horizontal_fling_scroll_(false), disallow_vertical_fling_scroll_(false), has_fling_animation_started_(false), - uma_latency_reporting_enabled_( - base::TimeTicks::IsHighResNowFastAndReliable()) { + uma_latency_reporting_enabled_(base::TimeTicks::IsHighResolution()) { DCHECK(client); input_handler_->BindToClient(this); smooth_scroll_enabled_ = base::CommandLine::ForCurrentProcess()->HasSwitch( @@ -217,7 +216,7 @@ if (uma_latency_reporting_enabled_) ReportInputEventLatencyUma(event, *latency_info); - TRACE_EVENT_FLOW_STEP0("input", + TRACE_EVENT_FLOW_STEP0("input,benchmark", "LatencyInfo.Flow", TRACE_ID_DONT_MANGLE(latency_info->trace_id), "HandleInputEventImpl"); @@ -231,7 +230,7 @@ InputHandlerProxy::EventDisposition InputHandlerProxy::HandleInputEvent( const WebInputEvent& event) { DCHECK(input_handler_); - TRACE_EVENT1("input", "InputHandlerProxy::HandleInputEvent", + TRACE_EVENT1("input,benchmark", "InputHandlerProxy::HandleInputEvent", "type", WebInputEventTraits::GetName(event.type)); client_->DidReceiveInputEvent(event.type);
diff --git a/content/renderer/media/media_stream_audio_processor.cc b/content/renderer/media/media_stream_audio_processor.cc index def508ba..54a8529 100644 --- a/content/renderer/media/media_stream_audio_processor.cc +++ b/content/renderer/media/media_stream_audio_processor.cc
@@ -86,7 +86,7 @@ if (command_line->HasSwitch(switches::kEnableDelayAgnosticAec)) return true; - return group_name == "Enabled"; + return (group_name == "Enabled" || group_name == "DefaultEnabled"); } } // namespace @@ -528,8 +528,7 @@ enabled = true; geometry.push_back(webrtc::Point(0.050f, 0.f, 0.f)); } else if (board == "swanky") { - // TODO(aluebs): Verify beamforming works on Swanky and enable. - enabled = false; + enabled = true; geometry.push_back(webrtc::Point(0.052f, 0.f, 0.f)); } #endif
diff --git a/content/renderer/media/media_stream_audio_processor_options.cc b/content/renderer/media/media_stream_audio_processor_options.cc index 0b8db59..b2465b33 100644 --- a/content/renderer/media/media_stream_audio_processor_options.cc +++ b/content/renderer/media/media_stream_audio_processor_options.cc
@@ -253,7 +253,7 @@ if (echo_total_delay_counts_ > 0) { poor_delay_frequency = static_cast<float>(echo_poor_delay_counts_) / static_cast<float>(echo_total_delay_counts_); - UMA_HISTOGRAM_ENUMERATION("Media.AecDelayBasedQuality", + UMA_HISTOGRAM_ENUMERATION("WebRTC.AecDelayBasedQuality", EchoDelayFrequencyToQuality(poor_delay_frequency), DELAY_BASED_ECHO_QUALITY_MAX); } @@ -266,7 +266,8 @@ #if defined(OS_ANDROID) || defined(OS_IOS) const std::string group_name = base::FieldTrialList::FindFullName("ReplaceAECMWithAEC"); - if (group_name.empty() || group_name != "Enabled") { + if (group_name.empty() || + !(group_name == "Enabled" || group_name == "DefaultEnabled")) { // Mobile devices are using AECM. int err = audio_processing->echo_control_mobile()->set_routing_mode( webrtc::EchoControlMobile::kSpeakerphone);
diff --git a/content/renderer/media/webrtc_local_audio_renderer.cc b/content/renderer/media/webrtc_local_audio_renderer.cc index 5fcd589..ca03f839 100644 --- a/content/renderer/media/webrtc_local_audio_renderer.cc +++ b/content/renderer/media/webrtc_local_audio_renderer.cc
@@ -16,7 +16,7 @@ #include "content/renderer/render_frame_impl.h" #include "media/audio/audio_output_device.h" #include "media/base/audio_bus.h" -#include "media/base/audio_fifo.h" +#include "media/base/audio_shifter.h" namespace content { @@ -36,21 +36,15 @@ TRACE_EVENT0("audio", "WebRtcLocalAudioRenderer::Render"); base::AutoLock auto_lock(thread_lock_); - if (!playing_ || !volume_ || !loopback_fifo_) { + if (!playing_ || !volume_ || !audio_shifter_) { audio_bus->Zero(); return 0; } - // Provide data by reading from the FIFO if the FIFO contains enough - // to fulfill the request. - if (loopback_fifo_->frames() >= audio_bus->frames()) { - loopback_fifo_->Consume(audio_bus, 0, audio_bus->frames()); - } else { - audio_bus->Zero(); - // This warning is perfectly safe if it happens for the first audio - // frames. It should not happen in a steady-state mode. - DVLOG(2) << "loopback FIFO is not full enough yet"; - } + audio_shifter_->Pull( + audio_bus, + base::TimeTicks::Now() - + base::TimeDelta::FromMilliseconds(audio_delay_milliseconds)); return audio_bus->frames(); } @@ -68,24 +62,16 @@ TRACE_EVENT0("audio", "WebRtcLocalAudioRenderer::CaptureData"); base::AutoLock auto_lock(thread_lock_); - if (!playing_ || !volume_ || !loopback_fifo_) + if (!playing_ || !volume_ || !audio_shifter_) return; - // Push captured audio to FIFO so it can be read by a local sink. - if ((loopback_fifo_->frames() + audio_bus.frames()) <= - loopback_fifo_->max_frames()) { - // TODO(miu): Make sure the Render() method accounts for time shifting - // appropriately, per the comments for the usage of the - // |estimated_capture_time| field found in media_stream_audio_sink.h. - // http://crbug.com/437064 - loopback_fifo_->Push(&audio_bus); - - const base::TimeTicks now = base::TimeTicks::Now(); - total_render_time_ += now - last_render_time_; - last_render_time_ = now; - } else { - DVLOG(1) << "FIFO is full"; - } + scoped_ptr<media::AudioBus> audio_data( + media::AudioBus::Create(audio_bus.channels(), audio_bus.frames())); + audio_bus.CopyTo(audio_data.get()); + audio_shifter_->Push(audio_data.Pass(), estimated_capture_time); + const base::TimeTicks now = base::TimeTicks::Now(); + total_render_time_ += now - last_render_time_; + last_render_time_ = now; } void WebRtcLocalAudioRenderer::OnSetFormat( @@ -152,7 +138,7 @@ { base::AutoLock auto_lock(thread_lock_); playing_ = false; - loopback_fifo_.reset(); + audio_shifter_.reset(); } // Stop the output audio stream, i.e, stop asking for data to render. @@ -246,7 +232,7 @@ { // Clear up the old data in the FIFO. base::AutoLock auto_lock(thread_lock_); - loopback_fifo_->Clear(); + audio_shifter_->Flush(); } if (!sink_params_.IsValid() || !playing_ || !volume_ || sink_started_) @@ -296,19 +282,19 @@ source_params_.effects() | implicit_ducking_effect); { - // TODO(henrika): we could add a more dynamic solution here but I prefer - // a fixed size combined with bad audio at overflow. The alternative is - // that we start to build up latency and that can be more difficult to - // detect. Tests have shown that the FIFO never contains more than 2 or 3 - // audio frames but I have selected a max size of ten buffers just - // in case since these tests were performed on a 16 core, 64GB Win 7 - // machine. We could also add some sort of error notifier in this area if - // the FIFO overflows. - media::AudioFifo* const new_fifo = new media::AudioFifo( - params.channels(), 10 * params.frames_per_buffer()); + // Note: The max buffer is fairly large, but will rarely be used. + // Cast needs the buffer to hold at least one second of audio. + // The clock accuracy is set to 20ms because clock accuracy is + // ~15ms on windows. + media::AudioShifter* const new_shifter = new media::AudioShifter( + base::TimeDelta::FromSeconds(2), + base::TimeDelta::FromMilliseconds(20), + base::TimeDelta::FromSeconds(20), + source_params_.sample_rate(), + params.channels()); base::AutoLock auto_lock(thread_lock_); - loopback_fifo_.reset(new_fifo); + audio_shifter_.reset(new_shifter); } if (!sink_.get())
diff --git a/content/renderer/media/webrtc_local_audio_renderer.h b/content/renderer/media/webrtc_local_audio_renderer.h index e84545de..69e7c8cb 100644 --- a/content/renderer/media/webrtc_local_audio_renderer.h +++ b/content/renderer/media/webrtc_local_audio_renderer.h
@@ -21,7 +21,7 @@ namespace media { class AudioBus; -class AudioFifo; +class AudioShifter; class AudioOutputDevice; class AudioParameters; } @@ -120,8 +120,8 @@ // The sink (destination) for rendered audio. scoped_refptr<media::AudioOutputDevice> sink_; - // Contains copies of captured audio frames. - scoped_ptr<media::AudioFifo> loopback_fifo_; + // This does all the synchronization/resampling/smoothing. + scoped_ptr<media::AudioShifter> audio_shifter_; // Stores last time a render callback was received. The time difference // between a new time stamp and this value can be used to derive the @@ -142,7 +142,7 @@ // Set when playing, cleared when paused. bool playing_; - // Protects |loopback_fifo_|, |playing_| and |sink_|. + // Protects |audio_shifter_|, |playing_| and |sink_|. mutable base::Lock thread_lock_; // The preferred buffer size provided via the ctor.
diff --git a/content/renderer/mojo/service_registry_js_wrapper.cc b/content/renderer/mojo/service_registry_js_wrapper.cc index 73a591e3..4840b1e 100644 --- a/content/renderer/mojo/service_registry_js_wrapper.cc +++ b/content/renderer/mojo/service_registry_js_wrapper.cc
@@ -6,7 +6,7 @@ #include "content/common/mojo/service_registry_impl.h" #include "content/public/common/service_registry.h" -#include "mojo/edk/js/handle.h" +#include "third_party/mojo/src/mojo/edk/js/handle.h" namespace content {
diff --git a/content/renderer/mojo/service_registry_js_wrapper.h b/content/renderer/mojo/service_registry_js_wrapper.h index 2be7f95..fa0eee9 100644 --- a/content/renderer/mojo/service_registry_js_wrapper.h +++ b/content/renderer/mojo/service_registry_js_wrapper.h
@@ -11,7 +11,7 @@ #include "gin/handle.h" #include "gin/object_template_builder.h" #include "gin/wrappable.h" -#include "mojo/public/cpp/system/core.h" +#include "third_party/mojo/src/mojo/public/cpp/system/core.h" namespace content {
diff --git a/content/renderer/pepper/plugin_instance_throttler_impl.cc b/content/renderer/pepper/plugin_instance_throttler_impl.cc index ea06846..a95f6db 100644 --- a/content/renderer/pepper/plugin_instance_throttler_impl.cc +++ b/content/renderer/pepper/plugin_instance_throttler_impl.cc
@@ -17,15 +17,6 @@ namespace { -const char kPowerSaverUnthrottleHistogram[] = "Plugin.PowerSaver.Unthrottle"; - -void RecordUnthrottleMethodMetric( - PluginInstanceThrottlerImpl::PowerSaverUnthrottleMethod method) { - UMA_HISTOGRAM_ENUMERATION( - kPowerSaverUnthrottleHistogram, method, - PluginInstanceThrottler::UNTHROTTLE_METHOD_NUM_ITEMS); -} - // When we give up waiting for a suitable preview frame, and simply suspend // the plugin where it's at. In milliseconds. const int kThrottleTimeout = 5000; @@ -39,6 +30,29 @@ } // namespace +// static +scoped_ptr<PluginInstanceThrottler> PluginInstanceThrottler::Get( + RenderFrame* frame, + const GURL& plugin_url, + PluginPowerSaverMode power_saver_mode) { + if (power_saver_mode == PluginPowerSaverMode::POWER_SAVER_MODE_ESSENTIAL) + return nullptr; + + bool power_saver_enabled = + power_saver_mode == + PluginPowerSaverMode::POWER_SAVER_MODE_PERIPHERAL_THROTTLED; + return make_scoped_ptr( + new PluginInstanceThrottlerImpl(frame, plugin_url, power_saver_enabled)); +} + +// static +void PluginInstanceThrottler::RecordUnthrottleMethodMetric( + PluginInstanceThrottlerImpl::PowerSaverUnthrottleMethod method) { + UMA_HISTOGRAM_ENUMERATION( + "Plugin.PowerSaver.Unthrottle", method, + PluginInstanceThrottler::UNTHROTTLE_METHOD_NUM_ITEMS); +} + PluginInstanceThrottlerImpl::PluginInstanceThrottlerImpl( RenderFrame* frame, const GURL& plugin_url, @@ -64,6 +78,8 @@ } PluginInstanceThrottlerImpl::~PluginInstanceThrottlerImpl() { + if (state_ != PLUGIN_INSTANCE_MARKED_ESSENTIAL) + RecordUnthrottleMethodMetric(UNTHROTTLE_METHOD_NEVER); } void PluginInstanceThrottlerImpl::AddObserver(Observer* observer) {
diff --git a/content/renderer/pepper/video_decoder_shim.cc b/content/renderer/pepper/video_decoder_shim.cc index e5c5bd0c..2aee847 100644 --- a/content/renderer/pepper/video_decoder_shim.cc +++ b/content/renderer/pepper/video_decoder_shim.cc
@@ -96,7 +96,7 @@ private: void OnPipelineStatus(media::PipelineStatus status); void DoDecode(); - void OnDecodeComplete(uint32_t decode_id, media::VideoDecoder::Status status); + void OnDecodeComplete(media::VideoDecoder::Status status); void OnOutputComplete(const scoped_refptr<media::VideoFrame>& frame); void OnResetComplete(); @@ -107,11 +107,12 @@ // Queue of decodes waiting for the decoder. typedef std::queue<PendingDecode> PendingDecodeQueue; PendingDecodeQueue pending_decodes_; - int max_decodes_at_decoder_; - int num_decodes_at_decoder_; + bool awaiting_decoder_; // VideoDecoder returns pictures without information about the decode buffer - // that generated it. Save the decode_id from the last decode that completed, - // which is close for most decoders, which only decode one buffer at a time. + // that generated it, but VideoDecoder implementations used in this class + // (media::FFmpegVideoDecoder and media::VpxVideoDecoder) always generate + // corresponding frames before decode is finished. |decode_id_| is used to + // store id of the current buffer while Decode() call is pending. uint32_t decode_id_; }; @@ -119,8 +120,7 @@ const base::WeakPtr<VideoDecoderShim>& proxy) : shim_(proxy), main_message_loop_(base::MessageLoopProxy::current()), - max_decodes_at_decoder_(0), - num_decodes_at_decoder_(0), + awaiting_decoder_(false), decode_id_(0) { } @@ -143,7 +143,11 @@ ffmpeg_video_decoder->set_decode_nalus(true); decoder_ = ffmpeg_video_decoder.Pass(); } - max_decodes_at_decoder_ = decoder_->GetMaxDecodeRequests(); + + // VpxVideoDecoder and FFmpegVideoDecoder support only one pending Decode() + // request. + DCHECK_EQ(decoder_->GetMaxDecodeRequests(), 1); + // We can use base::Unretained() safely in decoder callbacks because // |decoder_| is owned by DecoderImpl. During Stop(), the |decoder_| will be // destroyed and all outstanding callbacks will be fired. @@ -207,8 +211,7 @@ } // Calculate how many textures the shim should create. - uint32_t shim_texture_pool_size = - max_decodes_at_decoder_ + media::limits::kMaxVideoFrames; + uint32_t shim_texture_pool_size = media::limits::kMaxVideoFrames + 1; main_message_loop_->PostTask( FROM_HERE, base::Bind(&VideoDecoderShim::OnInitializeComplete, @@ -218,24 +221,22 @@ } void VideoDecoderShim::DecoderImpl::DoDecode() { - while (!pending_decodes_.empty() && - num_decodes_at_decoder_ < max_decodes_at_decoder_) { - num_decodes_at_decoder_++; - const PendingDecode& decode = pending_decodes_.front(); - decoder_->Decode( - decode.buffer, - base::Bind(&VideoDecoderShim::DecoderImpl::OnDecodeComplete, - base::Unretained(this), - decode.decode_id)); - pending_decodes_.pop(); - } + if (pending_decodes_.empty() || awaiting_decoder_) + return; + + awaiting_decoder_ = true; + const PendingDecode& decode = pending_decodes_.front(); + decode_id_ = decode.decode_id; + decoder_->Decode(decode.buffer, + base::Bind(&VideoDecoderShim::DecoderImpl::OnDecodeComplete, + base::Unretained(this))); + pending_decodes_.pop(); } void VideoDecoderShim::DecoderImpl::OnDecodeComplete( - uint32_t decode_id, media::VideoDecoder::Status status) { - num_decodes_at_decoder_--; - decode_id_ = decode_id; + DCHECK(awaiting_decoder_); + awaiting_decoder_ = false; int32_t result; switch (status) { @@ -255,13 +256,17 @@ main_message_loop_->PostTask( FROM_HERE, base::Bind( - &VideoDecoderShim::OnDecodeComplete, shim_, result, decode_id)); + &VideoDecoderShim::OnDecodeComplete, shim_, result, decode_id_)); DoDecode(); } void VideoDecoderShim::DecoderImpl::OnOutputComplete( const scoped_refptr<media::VideoFrame>& frame) { + // Software decoders are expected to generated frames only when a Decode() + // call is pending. + DCHECK(awaiting_decoder_); + scoped_ptr<PendingFrame> pending_frame; if (!frame->end_of_stream()) { pending_frame.reset(new PendingFrame(
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index f1eec338..f2498261 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -103,8 +103,6 @@ #include "media/blink/webmediaplayer_params.h" #include "media/filters/default_renderer_factory.h" #include "media/filters/gpu_video_accelerator_factories.h" -#include "mojo/edk/js/core.h" -#include "mojo/edk/js/support.h" #include "net/base/data_url.h" #include "net/base/net_errors.h" #include "net/base/registry_controlled_domains/registry_controlled_domain.h" @@ -133,6 +131,8 @@ #include "third_party/WebKit/public/web/WebSurroundingText.h" #include "third_party/WebKit/public/web/WebUserGestureIndicator.h" #include "third_party/WebKit/public/web/WebView.h" +#include "third_party/mojo/src/mojo/edk/js/core.h" +#include "third_party/mojo/src/mojo/edk/js/support.h" #if defined(ENABLE_PLUGINS) #include "content/renderer/npapi/webplugin_impl.h" @@ -422,6 +422,17 @@ RequestExtraData* extra_data = new RequestExtraData(); extra_data->set_stream_override(stream_override.Pass()); request.setExtraData(extra_data); + + // Set the ui timestamp for this navigation. Currently the timestamp here is + // only non empty when the navigation was triggered by an Android intent. The + // timestamp is converted to a double version supported by blink. It will be + // passed back to the browser in the DidCommitProvisionalLoad and the + // DocumentLoadComplete IPCs. + base::TimeDelta ui_timestamp = common_params.ui_timestamp - base::TimeTicks(); + request.setUiStartTime(ui_timestamp.InSecondsF()); + request.setInputPerfMetricReportPolicy( + static_cast<WebURLRequest::InputToLoadPerfMetricReportPolicy>( + common_params.report_type)); return request; } @@ -475,6 +486,17 @@ GURL(request->httpHeaderField(WebString::fromUTF8("Referer")).latin1()), request->referrerPolicy()); params.transition = extra_data->transition_type(); + + // Set the ui timestamp for this navigation. Currently the timestamp here is + // only non empty when the navigation was triggered by an Android intent, or + // by the user clicking on a link. The timestamp is converted from a double + // version supported by blink. It will be passed back to the renderer in the + // CommitNavigation IPC, and then back to the browser again in the + // DidCommitProvisionalLoad and the DocumentLoadComplete IPCs. + params.ui_timestamp = + base::TimeTicks() + base::TimeDelta::FromSecondsD(request->uiStartTime()); + params.report_type = static_cast<FrameMsg_UILoadMetricsReportType::Value>( + request->inputPerfMetricReportPolicy()); return params; } @@ -769,8 +791,8 @@ return; GetRenderWidget()->UpdateTextInputType(); - if (renderer_accessibility()) - renderer_accessibility()->FocusedNodeChanged(WebNode()); + + FocusedNodeChangedForAccessibility(WebNode()); } void RenderFrameImpl::PepperCaretPositionChanged( @@ -1999,10 +2021,18 @@ void RenderFrameImpl::didAccessInitialDocument(blink::WebLocalFrame* frame) { DCHECK(!frame_ || frame_ == frame); - // Notify the browser process that it is no longer safe to show the pending - // URL of the main frame, since a URL spoof is now possible. - if (!frame->parent() && render_view_->page_id_ == -1) - Send(new FrameHostMsg_DidAccessInitialDocument(routing_id_)); + // If the request hasn't yet committed, notify the browser process that it is + // no longer safe to show the pending URL of the main frame, since a URL spoof + // is now possible. (If the request has committed, the browser already knows.) + if (!frame->parent()) { + DocumentState* document_state = + DocumentState::FromDataSource(frame->dataSource()); + NavigationState* navigation_state = document_state->navigation_state(); + + if (!navigation_state->request_committed()) { + Send(new FrameHostMsg_DidAccessInitialDocument(routing_id_)); + } + } } // TODO(alexmos): Remove once Blink is updated to use the version that takes @@ -3824,8 +3854,12 @@ } void RenderFrameImpl::FocusedNodeChanged(const WebNode& node) { - if (renderer_accessibility_) - renderer_accessibility_->FocusedNodeChanged(node); + FOR_EACH_OBSERVER(RenderFrameObserver, observers_, FocusedNodeChanged(node)); +} + +void RenderFrameImpl::FocusedNodeChangedForAccessibility(const WebNode& node) { + if (renderer_accessibility()) + renderer_accessibility()->AccessibilityFocusedNodeChanged(node); } // PlzNavigate
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h index 463d3308..e4f2901a 100644 --- a/content/renderer/render_frame_impl.h +++ b/content/renderer/render_frame_impl.h
@@ -209,11 +209,15 @@ void HandleWebAccessibilityEvent(const blink::WebAXObject& obj, blink::WebAXEvent event); - // TODO(dmazzoni): the only reason this is here is to plumb it through to - // RendererAccessibility. It should be part of RenderFrameObserver, once - // blink has a separate accessibility tree per frame. + // The focused node changed to |node|. If focus was lost from this frame, + // |node| will be null. void FocusedNodeChanged(const blink::WebNode& node); + // TODO(dmazzoni): the only reason this is here is to plumb it through to + // RendererAccessibility. It should use the RenderFrameObserver method, once + // blink has a separate accessibility tree per frame. + void FocusedNodeChangedForAccessibility(const blink::WebNode& node); + #if defined(ENABLE_PLUGINS) // Notification that a PPAPI plugin has been created. void PepperPluginCreated(RendererPpapiHost* host);
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index ae8b74f..ef6dae7 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc
@@ -530,7 +530,7 @@ *base::CommandLine::ForCurrentProcess(); is_impl_side_painting_enabled_ = - command_line.HasSwitch(switches::kEnableImplSidePainting); + !command_line.HasSwitch(switches::kDisableImplSidePainting); cc_blink::WebLayerImpl::SetImplSidePaintingEnabled( is_impl_side_painting_enabled_);
diff --git a/content/renderer/render_thread_impl_browsertest.cc b/content/renderer/render_thread_impl_browsertest.cc index 1262fd1..3e4a795 100644 --- a/content/renderer/render_thread_impl_browsertest.cc +++ b/content/renderer/render_thread_impl_browsertest.cc
@@ -138,8 +138,16 @@ mock_process_.reset(new MockRenderProcess); test_task_counter_ = make_scoped_refptr(new TestTaskCounter()); + + // RenderThreadImpl expects the browser to pass these flags. + base::CommandLine* cmd = base::CommandLine::ForCurrentProcess(); + base::CommandLine::StringVector old_argv = cmd->argv(); + + cmd->AppendSwitchASCII(switches::kNumRasterThreads, "1"); thread_ = new RenderThreadImplForTest(test_helper_->GetChannelId(), test_task_counter_); + cmd->InitFromArgv(old_argv); + thread_->EnsureWebKitInitialized(); test_msg_filter_ = make_scoped_refptr(
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc index 79dce611..6f5017df 100644 --- a/content/renderer/render_view_impl.cc +++ b/content/renderer/render_view_impl.cc
@@ -1916,21 +1916,35 @@ Send(new ViewHostMsg_TakeFocus(routing_id_, true)); } -void RenderViewImpl::focusedNodeChanged(const WebNode& node) { +void RenderViewImpl::focusedNodeChanged(const WebNode& fromNode, + const WebNode& toNode) { has_scrolled_focused_editable_node_into_rect_ = false; gfx::Rect node_bounds; - if (!node.isNull() && node.isElementNode()) { - WebNode web_node = const_cast<WebNode&>(node); + if (!toNode.isNull() && toNode.isElementNode()) { + WebNode web_node = const_cast<WebNode&>(toNode); node_bounds = gfx::Rect(web_node.to<WebElement>().boundsInViewportSpace()); } - Send(new ViewHostMsg_FocusedNodeChanged(routing_id_, IsEditableNode(node), + Send(new ViewHostMsg_FocusedNodeChanged(routing_id_, IsEditableNode(toNode), node_bounds)); - FOR_EACH_OBSERVER(RenderViewObserver, observers_, FocusedNodeChanged(node)); + // TODO(estade): remove. + FOR_EACH_OBSERVER(RenderViewObserver, observers_, FocusedNodeChanged(toNode)); - // TODO(dmazzoni): this should be part of RenderFrameObserver. - GetMainRenderFrame()->FocusedNodeChanged(node); + RenderFrameImpl* previous_frame = nullptr; + if (!fromNode.isNull()) + previous_frame = RenderFrameImpl::FromWebFrame(fromNode.document().frame()); + RenderFrameImpl* new_frame = nullptr; + if (!toNode.isNull()) + new_frame = RenderFrameImpl::FromWebFrame(toNode.document().frame()); + + if (previous_frame && previous_frame != new_frame) + previous_frame->FocusedNodeChanged(WebNode()); + if (new_frame) + new_frame->FocusedNodeChanged(toNode); + + // TODO(dmazzoni): remove once there's a separate a11y tree per frame. + GetMainRenderFrame()->FocusedNodeChangedForAccessibility(toNode); } void RenderViewImpl::didUpdateLayout() {
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h index c5029e4..f8b0a313 100644 --- a/content/renderer/render_view_impl.h +++ b/content/renderer/render_view_impl.h
@@ -384,7 +384,8 @@ virtual bool acceptsLoadDrops(); virtual void focusNext(); virtual void focusPrevious(); - virtual void focusedNodeChanged(const blink::WebNode& node); + virtual void focusedNodeChanged(const blink::WebNode& fromNode, + const blink::WebNode& toNode); virtual void didUpdateLayout(); #if defined(OS_ANDROID) || defined(TOOLKIT_VIEWS) virtual bool didTapMultipleTargets(
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc index d737bfd..f8a148c 100644 --- a/content/renderer/render_widget.cc +++ b/content/renderer/render_widget.cc
@@ -1102,14 +1102,14 @@ &latency_info); base::TimeTicks start_time; - if (base::TimeTicks::IsHighResNowFastAndReliable()) - start_time = base::TimeTicks::HighResNow(); + if (base::TimeTicks::IsHighResolution()) + start_time = base::TimeTicks::Now(); - TRACE_EVENT1("renderer", "RenderWidget::OnHandleInputEvent", + TRACE_EVENT1("renderer,benchmark", "RenderWidget::OnHandleInputEvent", "event", WebInputEventTraits::GetName(input_event->type)); TRACE_EVENT_SYNTHETIC_DELAY_BEGIN("blink.HandleInputEvent"); TRACE_EVENT_FLOW_STEP0( - "input", + "input,benchmark", "LatencyInfo.Flow", TRACE_ID_DONT_MANGLE(latency_info.trace_id), "HanldeInputEventMain"); @@ -1207,13 +1207,13 @@ bool frame_pending = compositor_ && compositor_->BeginMainFrameRequested(); - // If we don't have a fast and accurate HighResNow, we assume the input - // handlers are heavy and rate limit them. + // If we don't have a fast and accurate Now(), we assume the input handlers + // are heavy and rate limit them. bool rate_limiting_wanted = input_event->type == WebInputEvent::MouseMove || input_event->type == WebInputEvent::MouseWheel; if (rate_limiting_wanted && !start_time.is_null()) { - base::TimeTicks end_time = base::TimeTicks::HighResNow(); + base::TimeTicks end_time = base::TimeTicks::Now(); total_input_handling_time_this_frame_ += (end_time - start_time); rate_limiting_wanted = total_input_handling_time_this_frame_.InMicroseconds() >
diff --git a/content/renderer/scheduler/cancelable_closure_holder.cc b/content/renderer/scheduler/cancelable_closure_holder.cc new file mode 100644 index 0000000..281a21d --- /dev/null +++ b/content/renderer/scheduler/cancelable_closure_holder.cc
@@ -0,0 +1,30 @@ +// 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 "content/renderer/scheduler/cancelable_closure_holder.h" + +namespace content { + +CancelableClosureHolder::CancelableClosureHolder() { +} + +CancelableClosureHolder::~CancelableClosureHolder() { +} + +void CancelableClosureHolder::Reset(const base::Closure& callback) { + callback_ = callback; + cancelable_callback_.Reset(callback_); +} + +void CancelableClosureHolder::Cancel() { + DCHECK(!callback_.is_null()); + cancelable_callback_.Reset(callback_); +} + +const base::Closure& CancelableClosureHolder::callback() const { + DCHECK(!callback_.is_null()); + return cancelable_callback_.callback(); +} + +} // namespace content
diff --git a/content/renderer/scheduler/cancelable_closure_holder.h b/content/renderer/scheduler/cancelable_closure_holder.h new file mode 100644 index 0000000..dc11e66b --- /dev/null +++ b/content/renderer/scheduler/cancelable_closure_holder.h
@@ -0,0 +1,39 @@ +// 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 CONTENT_RENDERER_SCHEDULER_CANCELABLE_CLOSURE_HOLDER_H_ +#define CONTENT_RENDERER_SCHEDULER_CANCELABLE_CLOSURE_HOLDER_H_ + +#include "base/cancelable_callback.h" + +namespace content { + +// A CancelableClosureHolder is a CancelableCallback which resets its wrapped +// callback with a cached closure whenever it is canceled. +class CancelableClosureHolder { + public: + CancelableClosureHolder(); + ~CancelableClosureHolder(); + + // Resets the closure to be wrapped by the cancelable callback. Cancels any + // outstanding callbacks. + void Reset(const base::Closure& callback); + + // Cancels any outstanding closures returned by callback(). + void Cancel(); + + // Returns a callback that will be disabled by calling Cancel(). Callback + // must have been set using Reset() before calling this function. + const base::Closure& callback() const; + + private: + base::Closure callback_; + base::CancelableClosure cancelable_callback_; + + DISALLOW_COPY_AND_ASSIGN(CancelableClosureHolder); +}; + +} // namespace content + +#endif // CONTENT_RENDERER_SCHEDULER_CANCELABLE_CLOSURE_HOLDER_H_
diff --git a/content/renderer/scheduler/renderer_scheduler_impl.cc b/content/renderer/scheduler/renderer_scheduler_impl.cc index aa6e71f9..9615fe3 100644 --- a/content/renderer/scheduler/renderer_scheduler_impl.cc +++ b/content/renderer/scheduler/renderer_scheduler_impl.cc
@@ -35,8 +35,8 @@ weak_renderer_scheduler_ptr_ = weak_factory_.GetWeakPtr(); update_policy_closure_ = base::Bind(&RendererSchedulerImpl::UpdatePolicy, weak_renderer_scheduler_ptr_); - end_idle_period_closure_ = base::Bind(&RendererSchedulerImpl::EndIdlePeriod, - weak_renderer_scheduler_ptr_); + end_idle_period_closure_.Reset(base::Bind( + &RendererSchedulerImpl::EndIdlePeriod, weak_renderer_scheduler_ptr_)); idle_task_runner_ = make_scoped_refptr(new SingleThreadIdleTaskRunner( task_queue_manager_->TaskRunnerForQueue(IDLE_TASK_QUEUE), base::Bind(&RendererSchedulerImpl::CurrentIdleTaskDeadlineCallback, @@ -111,7 +111,8 @@ base::TimeTicks now(Now()); if (now < estimated_next_frame_begin_) { StartIdlePeriod(); - control_task_runner_->PostDelayedTask(FROM_HERE, end_idle_period_closure_, + control_task_runner_->PostDelayedTask(FROM_HERE, + end_idle_period_closure_.callback(), estimated_next_frame_begin_ - now); } } @@ -178,8 +179,8 @@ void RendererSchedulerImpl::PostUpdatePolicyOnControlRunner( base::TimeDelta delay) { - control_task_runner_->PostDelayedTask(FROM_HERE, update_policy_closure_, - delay); + control_task_runner_->PostDelayedTask( + FROM_HERE, update_policy_closure_, delay); } void RendererSchedulerImpl::UpdatePolicy() { @@ -250,6 +251,7 @@ TRACE_EVENT_ASYNC_END0("renderer.scheduler", "RendererSchedulerIdlePeriod", this); main_thread_checker_.CalledOnValidThread(); + end_idle_period_closure_.Cancel(); renderer_task_queue_selector_->DisableQueue(IDLE_TASK_QUEUE); }
diff --git a/content/renderer/scheduler/renderer_scheduler_impl.h b/content/renderer/scheduler/renderer_scheduler_impl.h index d4fe054..ccf5881c 100644 --- a/content/renderer/scheduler/renderer_scheduler_impl.h +++ b/content/renderer/scheduler/renderer_scheduler_impl.h
@@ -8,6 +8,7 @@ #include "base/atomicops.h" #include "base/synchronization/lock.h" #include "base/threading/thread_checker.h" +#include "content/renderer/scheduler/cancelable_closure_holder.h" #include "content/renderer/scheduler/renderer_scheduler.h" #include "content/renderer/scheduler/single_thread_idle_task_runner.h" #include "content/renderer/scheduler/task_queue_manager.h" @@ -125,7 +126,7 @@ scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner_; base::Closure update_policy_closure_; - base::Closure end_idle_period_closure_; + CancelableClosureHolder end_idle_period_closure_; // Don't access current_policy_ directly, instead use SchedulerPolicy(). Policy current_policy_;
diff --git a/content/renderer/scheduler/renderer_scheduler_impl_unittest.cc b/content/renderer/scheduler/renderer_scheduler_impl_unittest.cc index f3fb6446..36c85d3 100644 --- a/content/renderer/scheduler/renderer_scheduler_impl_unittest.cc +++ b/content/renderer/scheduler/renderer_scheduler_impl_unittest.cc
@@ -256,6 +256,43 @@ EXPECT_EQ(2, run_count); } +TEST_F(RendererSchedulerImplTest, TestDelayedEndIdlePeriodCanceled) { + bool task_run = false; + + base::TimeTicks deadline_in_task; + idle_task_runner_->PostIdleTask( + FROM_HERE, base::Bind(&IdleTestTask, &task_run, &deadline_in_task)); + + // Trigger the beginning of an idle period for 1000ms. + scheduler_->WillBeginFrame(cc::BeginFrameArgs::Create( + BEGINFRAME_FROM_HERE, clock_->Now(), base::TimeTicks(), + base::TimeDelta::FromMilliseconds(1000), cc::BeginFrameArgs::NORMAL)); + scheduler_->DidCommitFrameToCompositor(); + + // End the idle period early (after 500ms), and send a WillBeginFrame which + // specifies that the next idle period should end 1000ms from now. + clock_->AdvanceNow(base::TimeDelta::FromMilliseconds(500)); + scheduler_->WillBeginFrame(cc::BeginFrameArgs::Create( + BEGINFRAME_FROM_HERE, clock_->Now(), base::TimeTicks(), + base::TimeDelta::FromMilliseconds(1000), cc::BeginFrameArgs::NORMAL)); + + RunUntilIdle(); + EXPECT_FALSE(task_run); // Not currently in an idle period. + + // Trigger the start of the idle period before the task to end the previous + // idle period has been triggered. + clock_->AdvanceNow(base::TimeDelta::FromMilliseconds(400)); + scheduler_->DidCommitFrameToCompositor(); + + // Post a task which simulates running until after the previous end idle + // period delayed task was scheduled for + scheduler_->DefaultTaskRunner()->PostTask(FROM_HERE, base::Bind(NullTask)); + clock_->AdvanceNow(base::TimeDelta::FromMilliseconds(300)); + + RunUntilIdle(); + EXPECT_TRUE(task_run); // We should still be in the new idle period. +} + TEST_F(RendererSchedulerImplTest, TestDefaultPolicy) { std::vector<std::string> order;
diff --git a/content/renderer/scheduler/web_scheduler_impl.cc b/content/renderer/scheduler/web_scheduler_impl.cc index c0a3407..1ca8a302 100644 --- a/content/renderer/scheduler/web_scheduler_impl.cc +++ b/content/renderer/scheduler/web_scheduler_impl.cc
@@ -28,6 +28,10 @@ task->run((deadline - base::TimeTicks()).InSecondsF()); } +void WebSchedulerImpl::runTask(scoped_ptr<blink::WebThread::Task> task) { + task->run(); +} + void WebSchedulerImpl::postIdleTask(const blink::WebTraceLocation& web_location, blink::WebScheduler::IdleTask* task) { scoped_ptr<blink::WebScheduler::IdleTask> scoped_task(task); @@ -38,6 +42,16 @@ base::Bind(&WebSchedulerImpl::runIdleTask, base::Passed(&scoped_task))); } +void WebSchedulerImpl::postLoadingTask( + const blink::WebTraceLocation& web_location, blink::WebThread::Task* task) { + scoped_ptr<blink::WebThread::Task> scoped_task(task); + tracked_objects::Location location(web_location.functionName(), + web_location.fileName(), -1, nullptr); + renderer_scheduler_->LoadingTaskRunner()->PostTask( + location, + base::Bind(&WebSchedulerImpl::runTask, base::Passed(&scoped_task))); +} + void WebSchedulerImpl::shutdown() { return renderer_scheduler_->Shutdown(); }
diff --git a/content/renderer/scheduler/web_scheduler_impl.h b/content/renderer/scheduler/web_scheduler_impl.h index 98bdaafc..dc31c0cc 100644 --- a/content/renderer/scheduler/web_scheduler_impl.h +++ b/content/renderer/scheduler/web_scheduler_impl.h
@@ -9,6 +9,7 @@ #include "base/memory/scoped_ptr.h" #include "base/time/time.h" #include "third_party/WebKit/public/platform/WebScheduler.h" +#include "third_party/WebKit/public/platform/WebThread.h" namespace content { @@ -23,11 +24,14 @@ virtual bool shouldYieldForHighPriorityWork(); virtual void postIdleTask(const blink::WebTraceLocation& location, blink::WebScheduler::IdleTask* task); + virtual void postLoadingTask(const blink::WebTraceLocation& location, + blink::WebThread::Task* task); virtual void shutdown(); private: static void runIdleTask(scoped_ptr<blink::WebScheduler::IdleTask> task, base::TimeTicks deadline); + static void runTask(scoped_ptr<blink::WebThread::Task> task); RendererScheduler* renderer_scheduler_; scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner_;
diff --git a/content/renderer/service_worker/embedded_worker_context_client.cc b/content/renderer/service_worker/embedded_worker_context_client.cc index eef9919..ccf3dcc 100644 --- a/content/renderer/service_worker/embedded_worker_context_client.cc +++ b/content/renderer/service_worker/embedded_worker_context_client.cc
@@ -15,7 +15,12 @@ #include "base/strings/utf_string_conversions.h" #include "base/threading/thread_local.h" #include "content/child/request_extra_data.h" +#include "content/child/service_worker/service_worker_dispatcher.h" #include "content/child/service_worker/service_worker_network_provider.h" +#include "content/child/service_worker/service_worker_provider_context.h" +#include "content/child/service_worker/service_worker_registration_handle_reference.h" +#include "content/child/service_worker/web_service_worker_impl.h" +#include "content/child/service_worker/web_service_worker_registration_impl.h" #include "content/child/thread_safe_sender.h" #include "content/child/worker_task_runner.h" #include "content/child/worker_thread_task_runner.h" @@ -23,6 +28,7 @@ #include "content/common/service_worker/embedded_worker_messages.h" #include "content/common/service_worker/service_worker_types.h" #include "content/public/renderer/document_state.h" +#include "content/renderer/devtools/devtools_agent.h" #include "content/renderer/render_thread_impl.h" #include "content/renderer/service_worker/embedded_worker_dispatcher.h" #include "content/renderer/service_worker/service_worker_script_context.h" @@ -36,8 +42,6 @@ namespace { -const size_t kMaxMessageChunkSize = IPC::Channel::kMaximumMessageSize / 4; - // For now client must be a per-thread instance. // TODO(kinuko): This needs to be refactored when we start using thread pool // or having multiple clients per one thread. @@ -176,6 +180,13 @@ g_worker_client_tls.Pointer()->Set(this); script_context_.reset(new ServiceWorkerScriptContext(this, proxy)); + // This can be nullptr on EmbeddedWorkerBrowserTests. + // TODO(nhiroki): Remove this workaround. |registration()| should always be + // valid other than the test because the registration association message + // arrives before starting the worker context. + if (provider_context_->registration()) + SetRegistrationInServiceWorkerGlobalScope(); + Send(new EmbeddedWorkerHostMsg_WorkerScriptLoaded( embedded_worker_id_, WorkerTaskRunner::Instance()->CurrentWorkerId())); @@ -248,28 +259,13 @@ embedded_worker_id_, params)); } -void EmbeddedWorkerContextClient::dispatchDevToolsMessage( - const blink::WebString& message) { - std::string msg(message.utf8()); - - if (msg.length() < kMaxMessageChunkSize) { - sender_->Send(new DevToolsClientMsg_DispatchOnInspectorFrontend( - worker_devtools_agent_route_id_, msg, msg.size())); - return; - } - - for (size_t pos = 0; pos < msg.length(); pos += kMaxMessageChunkSize) { - sender_->Send(new DevToolsClientMsg_DispatchOnInspectorFrontend( - worker_devtools_agent_route_id_, - msg.substr(pos, kMaxMessageChunkSize), - pos ? 0 : msg.size())); - } -} - -void EmbeddedWorkerContextClient::saveDevToolsAgentState( - const blink::WebString& state) { - sender_->Send(new DevToolsHostMsg_SaveAgentRuntimeState( - worker_devtools_agent_route_id_, state.utf8())); +void EmbeddedWorkerContextClient::sendDevToolsMessage( + int call_id, + const blink::WebString& message, + const blink::WebString& state_cookie) { + DevToolsAgent::SendChunkedProtocolMessage( + sender_.get(), worker_devtools_agent_route_id_, + call_id, message.utf8(), state_cookie.utf8()); } void EmbeddedWorkerContextClient::didHandleActivateEvent( @@ -348,10 +344,13 @@ blink::WebServiceWorkerNetworkProvider* EmbeddedWorkerContextClient::createServiceWorkerNetworkProvider( blink::WebDataSource* data_source) { + DCHECK(main_thread_proxy_->RunsTasksOnCurrentThread()); + // Create a content::ServiceWorkerNetworkProvider for this data source so // we can observe its requests. scoped_ptr<ServiceWorkerNetworkProvider> provider( new ServiceWorkerNetworkProvider(MSG_ROUTING_NONE)); + provider_context_ = provider->context(); // Tell the network provider about which version to load. provider->SetServiceWorkerVersionId(service_worker_version_id_); @@ -415,4 +414,33 @@ Send(new EmbeddedWorkerHostMsg_WorkerStarted(embedded_worker_id_)); } +void EmbeddedWorkerContextClient::SetRegistrationInServiceWorkerGlobalScope() { + DCHECK(worker_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(provider_context_); + DCHECK(script_context_); + + ServiceWorkerDispatcher* dispatcher = + ServiceWorkerDispatcher::GetOrCreateThreadSpecificInstance( + thread_safe_sender()); + + // Register a registration with the dispatcher living on the worker thread. + DCHECK(provider_context_->registration()); + scoped_ptr<WebServiceWorkerRegistrationImpl> registration( + dispatcher->CreateServiceWorkerRegistration( + provider_context_->registration()->info(), false)); + + // Register workers with the dispatcher living on the worker thread. + ServiceWorkerVersionAttributes attrs = + provider_context_->GetVersionAttributes(); + registration->SetInstalling( + dispatcher->GetServiceWorker(attrs.installing, false)); + registration->SetWaiting( + dispatcher->GetServiceWorker(attrs.waiting, false)); + registration->SetActive( + dispatcher->GetServiceWorker(attrs.active, false)); + + script_context_->SetRegistrationInServiceWorkerGlobalScope( + registration.Pass()); +} + } // namespace content
diff --git a/content/renderer/service_worker/embedded_worker_context_client.h b/content/renderer/service_worker/embedded_worker_context_client.h index 5e5f6014..9bdbeca 100644 --- a/content/renderer/service_worker/embedded_worker_context_client.h +++ b/content/renderer/service_worker/embedded_worker_context_client.h
@@ -29,6 +29,7 @@ namespace content { +class ServiceWorkerProviderContext; class ServiceWorkerScriptContext; class ThreadSafeSender; @@ -83,8 +84,9 @@ const blink::WebString& message, int line_number, const blink::WebString& source_url); - virtual void dispatchDevToolsMessage(const blink::WebString&); - virtual void saveDevToolsAgentState(const blink::WebString&); + virtual void sendDevToolsMessage(int call_id, + const blink::WebString& message, + const blink::WebString& state); virtual void didHandleActivateEvent(int request_id, blink::WebServiceWorkerEventResult); virtual void didHandleInstallEvent(int request_id, @@ -129,6 +131,7 @@ int embedded_worker_id, const IPC::Message& message); void SendWorkerStarted(); + void SetRegistrationInServiceWorkerGlobalScope(); const int embedded_worker_id_; const int64 service_worker_version_id_; @@ -140,6 +143,7 @@ scoped_refptr<base::TaskRunner> worker_task_runner_; scoped_ptr<ServiceWorkerScriptContext> script_context_; + scoped_refptr<ServiceWorkerProviderContext> provider_context_; base::WeakPtrFactory<EmbeddedWorkerContextClient> weak_factory_;
diff --git a/content/renderer/service_worker/service_worker_cache_storage_dispatcher.cc b/content/renderer/service_worker/service_worker_cache_storage_dispatcher.cc index e88c69f..423de5a 100644 --- a/content/renderer/service_worker/service_worker_cache_storage_dispatcher.cc +++ b/content/renderer/service_worker/service_worker_cache_storage_dispatcher.cc
@@ -12,6 +12,7 @@ #include "base/metrics/histogram_macros.h" #include "base/strings/utf_string_conversions.h" #include "content/common/service_worker/service_worker_messages.h" +#include "content/public/common/referrer.h" #include "content/public/renderer/render_thread.h" #include "content/renderer/service_worker/service_worker_script_context.h" #include "third_party/WebKit/public/platform/WebHTTPHeaderVisitor.h" @@ -52,10 +53,10 @@ ServiceWorkerHeaderMap headers; web_request.visitHTTPHeaderFields(MakeHeaderVisitor(&headers).get()); - return ServiceWorkerFetchRequest(web_request.url(), - base::UTF16ToASCII(web_request.method()), - headers, web_request.referrerUrl(), - web_request.isReload()); + return ServiceWorkerFetchRequest( + web_request.url(), base::UTF16ToASCII(web_request.method()), headers, + Referrer(web_request.referrerUrl(), web_request.referrerPolicy()), + web_request.isReload()); } void PopulateWebRequestFromFetchRequest( @@ -69,8 +70,8 @@ web_request->setHeader(base::ASCIIToUTF16(i->first), base::ASCIIToUTF16(i->second)); } - web_request->setReferrer(base::ASCIIToUTF16(request.referrer.spec()), - blink::WebReferrerPolicy::WebReferrerPolicyNever); + web_request->setReferrer(base::ASCIIToUTF16(request.referrer.url.spec()), + request.referrer.policy); web_request->setIsReload(request.is_reload); }
diff --git a/content/renderer/service_worker/service_worker_script_context.cc b/content/renderer/service_worker/service_worker_script_context.cc index dd0d523..4a360f1d 100644 --- a/content/renderer/service_worker/service_worker_script_context.cc +++ b/content/renderer/service_worker/service_worker_script_context.cc
@@ -8,10 +8,12 @@ #include "base/logging.h" #include "base/metrics/histogram.h" #include "content/child/notifications/notification_data_conversions.h" +#include "content/child/service_worker/web_service_worker_registration_impl.h" #include "content/child/thread_safe_sender.h" #include "content/child/webmessageportchannel_impl.h" #include "content/common/message_port_messages.h" #include "content/common/service_worker/service_worker_messages.h" +#include "content/public/common/referrer.h" #include "content/renderer/service_worker/embedded_worker_context_client.h" #include "ipc/ipc_message.h" #include "third_party/WebKit/public/platform/WebCrossOriginServiceWorkerClient.h" @@ -115,6 +117,11 @@ DCHECK(handled); } +void ServiceWorkerScriptContext::SetRegistrationInServiceWorkerGlobalScope( + scoped_ptr<WebServiceWorkerRegistrationImpl> registration) { + proxy_->setRegistration(registration.release()); +} + void ServiceWorkerScriptContext::DidHandleActivateEvent( int request_id, blink::WebServiceWorkerEventResult result) { @@ -284,8 +291,9 @@ webRequest.setBlob(blink::WebString::fromUTF8(request.blob_uuid), request.blob_size); } - webRequest.setReferrer(blink::WebString::fromUTF8(request.referrer.spec()), - blink::WebReferrerPolicyDefault); + webRequest.setReferrer( + blink::WebString::fromUTF8(request.referrer.url.spec()), + request.referrer.policy); webRequest.setMode(GetBlinkFetchRequestMode(request.mode)); webRequest.setCredentialsMode( GetBlinkFetchCredentialsMode(request.credentials_mode)); @@ -339,7 +347,7 @@ void ServiceWorkerScriptContext::OnCrossOriginConnectEvent( int request_id, - const CrossOriginServiceWorkerClient& client) { + const NavigatorConnectClient& client) { TRACE_EVENT0("ServiceWorker", "ServiceWorkerScriptContext::OnCrossOriginConnectEvent"); blink::WebCrossOriginServiceWorkerClient web_client; @@ -375,7 +383,7 @@ } void ServiceWorkerScriptContext::OnCrossOriginMessageToWorker( - const CrossOriginServiceWorkerClient& client, + const NavigatorConnectClient& client, const base::string16& message, const std::vector<int>& sent_message_port_ids, const std::vector<int>& new_routing_ids) {
diff --git a/content/renderer/service_worker/service_worker_script_context.h b/content/renderer/service_worker/service_worker_script_context.h index b8953f7..5c8ff2c 100644 --- a/content/renderer/service_worker/service_worker_script_context.h +++ b/content/renderer/service_worker/service_worker_script_context.h
@@ -36,8 +36,9 @@ namespace content { -struct CrossOriginServiceWorkerClient; class EmbeddedWorkerContextClient; +class WebServiceWorkerRegistrationImpl; +struct NavigatorConnectClient; struct PlatformNotificationData; // TODO(kinuko): This should implement WebServiceWorkerContextClient @@ -53,6 +54,8 @@ void OnMessageReceived(const IPC::Message& message); + void SetRegistrationInServiceWorkerGlobalScope( + scoped_ptr<WebServiceWorkerRegistrationImpl> registration); void DidHandleActivateEvent(int request_id, blink::WebServiceWorkerEventResult); void DidHandleInstallEvent(int request_id, @@ -114,12 +117,12 @@ const std::string& region_id, const blink::WebCircularGeofencingRegion& region); void OnCrossOriginConnectEvent(int request_id, - const CrossOriginServiceWorkerClient& client); + const NavigatorConnectClient& client); void OnPostMessage(const base::string16& message, const std::vector<int>& sent_message_port_ids, const std::vector<int>& new_routing_ids); void OnCrossOriginMessageToWorker( - const CrossOriginServiceWorkerClient& client, + const NavigatorConnectClient& client, const base::string16& message, const std::vector<int>& sent_message_port_ids, const std::vector<int>& new_routing_ids);
diff --git a/content/renderer/shared_worker/embedded_shared_worker_stub.cc b/content/renderer/shared_worker/embedded_shared_worker_stub.cc index a2b6639..d026cec 100644 --- a/content/renderer/shared_worker/embedded_shared_worker_stub.cc +++ b/content/renderer/shared_worker/embedded_shared_worker_stub.cc
@@ -171,14 +171,11 @@ ChildThread::current()->thread_safe_sender()); } -void EmbeddedSharedWorkerStub::dispatchDevToolsMessage( - const blink::WebString& message) { - worker_devtools_agent_->SendDevToolsMessage(message); -} - -void EmbeddedSharedWorkerStub::saveDevToolsAgentState( - const blink::WebString& state) { - worker_devtools_agent_->SaveDevToolsAgentState(state); +void EmbeddedSharedWorkerStub::sendDevToolsMessage( + int call_id, + const blink::WebString& message, + const blink::WebString& state) { + worker_devtools_agent_->SendDevToolsMessage(call_id, message, state); } void EmbeddedSharedWorkerStub::Shutdown() {
diff --git a/content/renderer/shared_worker/embedded_shared_worker_stub.h b/content/renderer/shared_worker/embedded_shared_worker_stub.h index c710efa0..c698ef6 100644 --- a/content/renderer/shared_worker/embedded_shared_worker_stub.h +++ b/content/renderer/shared_worker/embedded_shared_worker_stub.h
@@ -58,9 +58,10 @@ virtual blink::WebWorkerPermissionClientProxy* createWorkerPermissionClientProxy( const blink::WebSecurityOrigin& origin) override; - virtual void dispatchDevToolsMessage( - const blink::WebString& message) override; - virtual void saveDevToolsAgentState(const blink::WebString& state) override; + virtual void sendDevToolsMessage( + int call_id, + const blink::WebString& message, + const blink::WebString& state) override; private: ~EmbeddedSharedWorkerStub() override;
diff --git a/content/renderer/skia_benchmarking_extension.cc b/content/renderer/skia_benchmarking_extension.cc index 8cf6edd..dccf88d 100644 --- a/content/renderer/skia_benchmarking_extension.cc +++ b/content/renderer/skia_benchmarking_extension.cc
@@ -263,9 +263,9 @@ bitmap.allocN32Pixels(bounds.width(), bounds.height()); SkCanvas bitmap_canvas(bitmap); bitmap_canvas.clear(SK_ColorTRANSPARENT); - base::TimeTicks t0 = base::TimeTicks::HighResNow(); + base::TimeTicks t0 = base::TimeTicks::Now(); picture->Replay(&bitmap_canvas); - base::TimeDelta total_time = base::TimeTicks::HighResNow() - t0; + base::TimeDelta total_time = base::TimeTicks::Now() - t0; // Gather per-op timing info by drawing into a BenchmarkingCanvas. skia::BenchmarkingCanvas benchmarking_canvas(bounds.width(), bounds.height());
diff --git a/content/renderer/web_ui_mojo.h b/content/renderer/web_ui_mojo.h index dd9e752..d851a62 100644 --- a/content/renderer/web_ui_mojo.h +++ b/content/renderer/web_ui_mojo.h
@@ -10,7 +10,7 @@ #include "content/public/renderer/render_frame_observer.h" #include "content/public/renderer/render_view_observer.h" #include "content/public/renderer/render_view_observer_tracker.h" -#include "mojo/public/cpp/system/core.h" +#include "third_party/mojo/src/mojo/public/cpp/system/core.h" namespace gin { class PerContextData;
diff --git a/content/shell/renderer/test_runner/web_test_proxy.cc b/content/shell/renderer/test_runner/web_test_proxy.cc index ee2ba35..c5eb35b4 100644 --- a/content/shell/renderer/test_runner/web_test_proxy.cc +++ b/content/shell/renderer/test_runner/web_test_proxy.cc
@@ -295,7 +295,7 @@ std::string result = DumpFrameHeaderIfNeeded(frame); result.append( - frame->renderTreeAsText(blink::WebFrame::RenderAsTextPrinting).utf8()); + frame->layoutTreeAsText(blink::WebFrame::LayoutAsTextPrinting).utf8()); result.append("\n"); if (recursive) { @@ -438,13 +438,13 @@ } else { bool recursive = test_interfaces_->GetTestRunner() ->shouldDumpChildFrameScrollPositions(); - blink::WebFrame::RenderAsTextControls render_text_behavior = - blink::WebFrame::RenderAsTextNormal; + blink::WebFrame::LayoutAsTextControls layout_text_behavior = + blink::WebFrame::LayoutAsTextNormal; if (should_dump_as_printed) - render_text_behavior |= blink::WebFrame::RenderAsTextPrinting; + layout_text_behavior |= blink::WebFrame::LayoutAsTextPrinting; if (debug_render_tree) - render_text_behavior |= blink::WebFrame::RenderAsTextDebug; - data_utf8 = frame->renderTreeAsText(render_text_behavior).utf8(); + layout_text_behavior |= blink::WebFrame::LayoutAsTextDebug; + data_utf8 = frame->layoutTreeAsText(layout_text_behavior).utf8(); data_utf8 += DumpFrameScrollPosition(frame, recursive); }
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index 45bd97c..b8e13de 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -595,6 +595,7 @@ if (!use_aura && !is_mac) { sources -= [ "../browser/compositor/buffer_queue_unittest.cc", + "../browser/compositor/reflector_impl_unittest.cc", "../browser/compositor/software_browser_compositor_output_surface_unittest.cc", ] }
diff --git a/content/test/data/accessibility/event/text-changed-expected-win.txt b/content/test/data/accessibility/event/text-changed-expected-win.txt index 78073cb..98953b9bd 100644 --- a/content/test/data/accessibility/event/text-changed-expected-win.txt +++ b/content/test/data/accessibility/event/text-changed-expected-win.txt
@@ -3,4 +3,3 @@ IA2_EVENT_TEXT_INSERTED on role=P new_text={'Modified ' start=0 end=9} EVENT_OBJECT_NAMECHANGE on role=ROLE_SYSTEM_STATICTEXT name="Modified Heading" IA2_EVENT_TEXT_INSERTED on role=h2 name="Heading" new_text={'Modified ' start=0 end=9} -EVENT_OBJECT_REORDER on role=P
diff --git a/content/test/data/accessibility/event/text-changed.html b/content/test/data/accessibility/event/text-changed.html index 4d2ad0e6..22d3357d 100644 --- a/content/test/data/accessibility/event/text-changed.html +++ b/content/test/data/accessibility/event/text-changed.html
@@ -1,3 +1,7 @@ +<!-- +The children changed / reorder event is fired an unpredictable number of times. +@WIN-DENY:EVENT_OBJECT_REORDER* +--> <!DOCTYPE html> <html> <body>
diff --git a/content/test/data/accessibility/html/a-no-text-expected-android.txt b/content/test/data/accessibility/html/a-no-text-expected-android.txt index 50f4d40..6dd6b11b5 100644 --- a/content/test/data/accessibility/html/a-no-text-expected-android.txt +++ b/content/test/data/accessibility/html/a-no-text-expected-android.txt
@@ -1,12 +1,12 @@ android.webkit.WebView focusable focused scrollable android.view.View - android.view.View clickable focusable name='dest1' - android.view.View clickable focusable name='dest2' - android.view.View clickable focusable name='dest3' - android.view.View clickable focusable name='dest4' - android.view.View clickable focusable name='dest5' - android.view.View clickable focusable name='dest6' - android.view.View clickable focusable name='dest7' - android.view.View clickable focusable name='dest.8' - android.view.View clickable focusable name='dest9' - android.view.View clickable focusable name='dest10' + android.view.View clickable focusable link name='dest1' + android.view.View clickable focusable link name='dest2' + android.view.View clickable focusable link name='dest3' + android.view.View clickable focusable link name='dest4' + android.view.View clickable focusable link name='dest5' + android.view.View clickable focusable link name='dest6' + android.view.View clickable focusable link name='dest7' + android.view.View clickable focusable link name='dest.8' + android.view.View clickable focusable link name='greenbox' + android.view.View clickable focusable link name='greenbox'
diff --git a/content/test/data/font/dwrite_font_cache_arial.dat b/content/test/data/font/dwrite_font_cache_arial.dat index 79bcd4a..979b760 100644 --- a/content/test/data/font/dwrite_font_cache_arial.dat +++ b/content/test/data/font/dwrite_font_cache_arial.dat Binary files differ
diff --git a/content/test/data/font/dwrite_font_cache_corrupt.dat b/content/test/data/font/dwrite_font_cache_corrupt.dat index d7a1405..b2c6a293 100644 --- a/content/test/data/font/dwrite_font_cache_corrupt.dat +++ b/content/test/data/font/dwrite_font_cache_corrupt.dat Binary files differ
diff --git a/content/test/data/render_frame_host/focus.html b/content/test/data/render_frame_host/focus.html new file mode 100644 index 0000000..27e5841d --- /dev/null +++ b/content/test/data/render_frame_host/focus.html
@@ -0,0 +1,17 @@ +<!DOCTYPE html> +<html> +<head> +</head> +<body> + <iframe name='frame1' src='data:text/html,<input><div>frame1</div>'></iframe> + <iframe name='frame2' src='data:text/html,<input><div>frame2</div>'></iframe> +</body> +<script> + function focusframe1() { + frames[0].focus(); + } + function focusframe2() { + frames[1].focus(); + } +</script> +</html>
diff --git a/content/test/gpu/gpu_tests/context_lost.py b/content/test/gpu/gpu_tests/context_lost.py index db5ced4..830937c 100644 --- a/content/test/gpu/gpu_tests/context_lost.py +++ b/content/test/gpu/gpu_tests/context_lost.py
@@ -321,6 +321,11 @@ enabled = True test = _ContextLostValidator + + @classmethod + def Name(cls): + return 'context_lost' + def CreateExpectations(self): return context_lost_expectations.ContextLostExpectations()
diff --git a/content/test/gpu/gpu_tests/gpu_process.py b/content/test/gpu/gpu_tests/gpu_process.py index d9e3ce5..91d43c1 100644 --- a/content/test/gpu/gpu_tests/gpu_process.py +++ b/content/test/gpu/gpu_tests/gpu_process.py
@@ -37,6 +37,10 @@ """Tests that accelerated content triggers the creation of a GPU process""" test = _GpuProcessValidator + @classmethod + def Name(cls): + return 'gpu_process' + def CreateExpectations(self): return expectations.GpuProcessExpectations()
diff --git a/content/test/gpu/gpu_tests/gpu_rasterization.py b/content/test/gpu/gpu_tests/gpu_rasterization.py index 39146cfe..404ed6e 100644 --- a/content/test/gpu/gpu_tests/gpu_rasterization.py +++ b/content/test/gpu/gpu_tests/gpu_rasterization.py
@@ -67,6 +67,10 @@ """Tests that GPU rasterization produces valid content""" test = _GpuRasterizationValidator + @classmethod + def Name(cls): + return 'gpu_rasterization' + def CreatePageSet(self, options): page_set = page_sets.GpuRasterizationTestsPageSet() for page in page_set.pages:
diff --git a/content/test/gpu/gpu_tests/hardware_accelerated_feature.py b/content/test/gpu/gpu_tests/hardware_accelerated_feature.py index 9b140b6..af81c0d2 100644 --- a/content/test/gpu/gpu_tests/hardware_accelerated_feature.py +++ b/content/test/gpu/gpu_tests/hardware_accelerated_feature.py
@@ -49,6 +49,10 @@ """Tests GPU acceleration is reported as active for various features""" test = _HardwareAcceleratedFeatureValidator + @classmethod + def Name(cls): + return 'hardware_accelerated_feature' + def CreateExpectations(self): return expectations.HardwareAcceleratedFeatureExpectations()
diff --git a/content/test/gpu/gpu_tests/maps.py b/content/test/gpu/gpu_tests/maps.py index 079d69eb..430657d 100644 --- a/content/test/gpu/gpu_tests/maps.py +++ b/content/test/gpu/gpu_tests/maps.py
@@ -90,6 +90,10 @@ """Google Maps pixel tests.""" test = _MapsValidator + @classmethod + def Name(cls): + return 'maps' + def CreateExpectations(self): return maps_expectations.MapsExpectations()
diff --git a/content/test/gpu/gpu_tests/memory_test.py b/content/test/gpu/gpu_tests/memory_test.py index 5ff6a437..576f13f 100644 --- a/content/test/gpu/gpu_tests/memory_test.py +++ b/content/test/gpu/gpu_tests/memory_test.py
@@ -103,6 +103,10 @@ """Tests GPU memory limits""" test = _MemoryValidator + @classmethod + def Name(cls): + return 'memory_test' + def CreateExpectations(self): return memory_test_expectations.MemoryTestExpectations()
diff --git a/content/test/gpu/gpu_tests/pixel.py b/content/test/gpu/gpu_tests/pixel.py index 6613daea..6db39cbe 100644 --- a/content/test/gpu/gpu_tests/pixel.py +++ b/content/test/gpu/gpu_tests/pixel.py
@@ -150,6 +150,10 @@ test = _PixelValidator @classmethod + def Name(cls): + return 'pixel' + + @classmethod def AddBenchmarkCommandLineArgs(cls, group): super(Pixel, cls).AddBenchmarkCommandLineArgs(group) group.add_option('--reference-dir',
diff --git a/content/test/gpu/gpu_tests/screenshot_sync.py b/content/test/gpu/gpu_tests/screenshot_sync.py index 7f4a5e2..f482c62 100644 --- a/content/test/gpu/gpu_tests/screenshot_sync.py +++ b/content/test/gpu/gpu_tests/screenshot_sync.py
@@ -48,6 +48,10 @@ they were requested""" test = _ScreenshotSyncValidator + @classmethod + def Name(cls): + return 'screenshot_sync' + def CreateExpectations(self): return expectations.ScreenshotSyncExpectations()
diff --git a/content/test/gpu/gpu_tests/trace_test.py b/content/test/gpu/gpu_tests/trace_test.py index 128448de..fb4de0f 100644 --- a/content/test/gpu/gpu_tests/trace_test.py +++ b/content/test/gpu/gpu_tests/trace_test.py
@@ -59,6 +59,10 @@ """Tests GPU traces""" test = _TraceValidator + @classmethod + def Name(cls): + return 'trace_test' + def CreateExpectations(self): return trace_test_expectations.TraceTestExpectations()
diff --git a/content/test/gpu/gpu_tests/webgl_conformance.py b/content/test/gpu/gpu_tests/webgl_conformance.py index 50d19f3..1de2fbb 100644 --- a/content/test/gpu/gpu_tests/webgl_conformance.py +++ b/content/test/gpu/gpu_tests/webgl_conformance.py
@@ -103,6 +103,10 @@ super(WebglConformance, self).__init__(max_failures=10) @classmethod + def Name(cls): + return 'webgl_conformance' + + @classmethod def AddBenchmarkCommandLineArgs(cls, group): group.add_option('--webgl-conformance-version', help='Version of the WebGL conformance tests to run.',
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py index 5b3f0d3..a9bbad1 100644 --- a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py +++ b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
@@ -53,6 +53,12 @@ self.Fail('conformance/textures/texparameter-test.html', ['win', 'amd', 'd3d9'], bug=839) # angle bug ID + # Win / D3D9 failures + self.Fail('conformance/extensions/oes-texture-float-with-canvas.html', + ['win', 'd3d9'], bug=896) # angle bug ID + self.Fail('conformance/extensions/oes-texture-half-float-with-canvas.html', + ['win', 'd3d9'], bug=896) # angle bug ID + # Mac / Intel failures # Radar 13499466 self.Fail('conformance/limits/gl-max-texture-dimensions.html',
diff --git a/content/test/gpu/gpu_tests/webgl_robustness.py b/content/test/gpu/gpu_tests/webgl_robustness.py index d1230a3..0612760 100644 --- a/content/test/gpu/gpu_tests/webgl_robustness.py +++ b/content/test/gpu/gpu_tests/webgl_robustness.py
@@ -61,6 +61,10 @@ class WebglRobustness(benchmark.Benchmark): test = WebglConformanceValidator + @classmethod + def Name(cls): + return 'webgl_robustness' + def CreatePageSet(self, options): ps = page_set.PageSet( file_path=conformance_path,
diff --git a/content/test/gpu/run_gpu_test.py b/content/test/gpu/run_gpu_test.py index a890d31..0cdfbf07 100755 --- a/content/test/gpu/run_gpu_test.py +++ b/content/test/gpu/run_gpu_test.py
@@ -4,6 +4,8 @@ # found in the LICENSE file. import os +import re +import subprocess import sys sys.path.append(os.path.join(os.path.dirname(__file__), @@ -13,7 +15,84 @@ from telemetry.core import environment +def _LaunchDBus(): + """Launches DBus to work around a bug in GLib. + + Works around a bug in GLib where it performs operations which aren't + async-signal-safe (in particular, memory allocations) between fork and exec + when it spawns subprocesses. This causes threads inside Chrome's browser and + utility processes to get stuck, and this harness to hang waiting for those + processes, which will never terminate. This doesn't happen on users' + machines, because they have an active desktop session and the + DBUS_SESSION_BUS_ADDRESS environment variable set, but it does happen on the + bots. See crbug.com/309093 for more details. + + Returns: + True if it actually spawned DBus. + """ + import platform + if (platform.uname()[0].lower() != 'linux' or + 'DBUS_SESSION_BUS_ADDRESS' in os.environ): + return False + + # Only start DBus on systems that are actually running X. Using DISPLAY + # variable is not reliable, because is it set by the /etc/init.d/buildbot + # script for all slaves. + # TODO(sergiyb): When all GPU slaves are migrated to swarming, we can remove + # assignment of the DISPLAY from /etc/init.d/buildbot because this hack was + # used to run GPU tests on buildbot. After it is removed, we can use DISPLAY + # variable here to check if we are running X. + if subprocess.call(['pidof', 'X'], stdout=subprocess.PIPE) == 0: + try: + print 'DBUS_SESSION_BUS_ADDRESS env var not found, starting dbus-launch' + dbus_output = subprocess.check_output(['dbus-launch']).split('\n') + for line in dbus_output: + m = re.match(r'([^=]+)\=(.+)', line) + if m: + os.environ[m.group(1)] = m.group(2) + print ' setting %s to %s' % (m.group(1), m.group(2)) + return True + except (subprocess.CalledProcessError, OSError) as e: + print 'Exception while running dbus_launch: %s' % e + return False + + +def _ShutdownDBus(): + """Manually kills the previously-launched DBus daemon. + + It appears that passing --exit-with-session to dbus-launch in + _LaunchDBus(), above, doesn't cause the launched dbus-daemon to shut + down properly. Manually kill the sub-process using the PID it gave + us at launch time. + + This function is called when the flag --spawn-dbus is given, and if + _LaunchDBus(), above, actually spawned the dbus-daemon. + """ + import signal + if 'DBUS_SESSION_BUS_PID' in os.environ: + dbus_pid = os.environ['DBUS_SESSION_BUS_PID'] + try: + os.kill(int(dbus_pid), signal.SIGTERM) + print ' killed dbus-daemon with PID %s' % dbus_pid + except OSError as e: + print ' error killing dbus-daemon with PID %s: %s' % (dbus_pid, e) + # Try to clean up any stray DBUS_SESSION_BUS_ADDRESS environment + # variable too. Some of the bots seem to re-invoke runtest.py in a + # way that this variable sticks around from run to run. + if 'DBUS_SESSION_BUS_ADDRESS' in os.environ: + del os.environ['DBUS_SESSION_BUS_ADDRESS'] + print ' cleared DBUS_SESSION_BUS_ADDRESS environment variable' + + if __name__ == '__main__': base_dir = os.path.dirname(os.path.realpath(__file__)) benchmark_runner.config = environment.Environment([base_dir]) - sys.exit(benchmark_runner.main()) + + did_launch_dbus = _LaunchDBus() + try: + retcode = benchmark_runner.main() + finally: + if did_launch_dbus: + _ShutdownDBus() + + sys.exit(retcode)
diff --git a/dbus/object_proxy.cc b/dbus/object_proxy.cc index c11f1fe..7347db0 100644 --- a/dbus/object_proxy.cc +++ b/dbus/object_proxy.cc
@@ -168,17 +168,20 @@ OnConnectedCallback on_connected_callback) { bus_->AssertOnOriginThread(); - base::PostTaskAndReplyWithResult( - bus_->GetDBusTaskRunner(), - FROM_HERE, - base::Bind(&ObjectProxy::ConnectToSignalInternal, - this, - interface_name, - signal_name, - signal_callback), - base::Bind(on_connected_callback, - interface_name, - signal_name)); + if (bus_->HasDBusThread()) { + base::PostTaskAndReplyWithResult( + bus_->GetDBusTaskRunner(), FROM_HERE, + base::Bind(&ObjectProxy::ConnectToSignalInternal, this, interface_name, + signal_name, signal_callback), + base::Bind(on_connected_callback, interface_name, signal_name)); + } else { + // If the bus doesn't have a dedicated dbus thread we need to call + // ConnectToSignalInternal directly otherwise we might miss a signal + // that is currently queued if we do a PostTask. + const bool success = + ConnectToSignalInternal(interface_name, signal_name, signal_callback); + on_connected_callback.Run(interface_name, signal_name, success); + } } void ObjectProxy::SetNameOwnerChangedCallback(
diff --git a/device/DEPS b/device/DEPS index 80961ee9..82ab498 100644 --- a/device/DEPS +++ b/device/DEPS
@@ -1,4 +1,4 @@ include_rules = [ "+chromeos", - "+mojo/public", + "+third_party/mojo/src/mojo/public", ]
diff --git a/device/battery/battery_monitor_impl.h b/device/battery/battery_monitor_impl.h index 49e85708..7fb1c139 100644 --- a/device/battery/battery_monitor_impl.h +++ b/device/battery/battery_monitor_impl.h
@@ -11,7 +11,7 @@ #include "device/battery/battery_export.h" #include "device/battery/battery_monitor.mojom.h" #include "device/battery/battery_status_service.h" -#include "mojo/public/cpp/bindings/strong_binding.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/strong_binding.h" namespace device {
diff --git a/device/bluetooth/BUILD.gn b/device/bluetooth/BUILD.gn index d08f74f..056a5fa7 100644 --- a/device/bluetooth/BUILD.gn +++ b/device/bluetooth/BUILD.gn
@@ -7,6 +7,8 @@ config("bluetooth_config") { if (is_win) { ldflags = [ + "/DELAYLOAD:BluetoothApis.dll", + # Despite MSDN stating that Bthprops.dll contains the # symbols declared by bthprops.lib, they actually reside here: "/DELAYLOAD:Bthprops.cpl", @@ -63,6 +65,8 @@ "bluetooth_init_win.h", "bluetooth_l2cap_channel_mac.mm", "bluetooth_l2cap_channel_mac.h", + "bluetooth_low_energy_defs_win.cc", + "bluetooth_low_energy_defs_win.h", "bluetooth_low_energy_win.cc", "bluetooth_low_energy_win.h", "bluetooth_pairing_chromeos.cc",
diff --git a/device/serial/data_receiver.h b/device/serial/data_receiver.h index 14bcdf31..942bb5c 100644 --- a/device/serial/data_receiver.h +++ b/device/serial/data_receiver.h
@@ -13,7 +13,7 @@ #include "base/memory/weak_ptr.h" #include "device/serial/buffer.h" #include "device/serial/data_stream.mojom.h" -#include "mojo/public/cpp/system/data_pipe.h" +#include "third_party/mojo/src/mojo/public/cpp/system/data_pipe.h" namespace device {
diff --git a/device/serial/data_sender.h b/device/serial/data_sender.h index c056afb..f4db8bc 100644 --- a/device/serial/data_sender.h +++ b/device/serial/data_sender.h
@@ -12,7 +12,7 @@ #include "base/strings/string_piece.h" #include "device/serial/buffer.h" #include "device/serial/data_stream.mojom.h" -#include "mojo/public/cpp/system/data_pipe.h" +#include "third_party/mojo/src/mojo/public/cpp/system/data_pipe.h" namespace device {
diff --git a/device/serial/data_sink_receiver.h b/device/serial/data_sink_receiver.h index e8c3e0e..2126cdd9 100644 --- a/device/serial/data_sink_receiver.h +++ b/device/serial/data_sink_receiver.h
@@ -13,7 +13,7 @@ #include "base/memory/weak_ptr.h" #include "device/serial/buffer.h" #include "device/serial/data_stream.mojom.h" -#include "mojo/public/cpp/system/data_pipe.h" +#include "third_party/mojo/src/mojo/public/cpp/system/data_pipe.h" namespace device {
diff --git a/device/serial/data_sink_unittest.cc b/device/serial/data_sink_unittest.cc index 29f3587..24843623 100644 --- a/device/serial/data_sink_unittest.cc +++ b/device/serial/data_sink_unittest.cc
@@ -9,9 +9,9 @@ #include "device/serial/data_sender.h" #include "device/serial/data_sink_receiver.h" #include "device/serial/data_stream.mojom.h" -#include "mojo/public/cpp/bindings/interface_ptr.h" -#include "mojo/public/cpp/environment/async_waiter.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_ptr.h" +#include "third_party/mojo/src/mojo/public/cpp/environment/async_waiter.h" namespace device {
diff --git a/device/serial/data_source_sender.h b/device/serial/data_source_sender.h index bdd3121..3a90240f 100644 --- a/device/serial/data_source_sender.h +++ b/device/serial/data_source_sender.h
@@ -12,7 +12,7 @@ #include "base/memory/weak_ptr.h" #include "device/serial/buffer.h" #include "device/serial/data_stream.mojom.h" -#include "mojo/public/cpp/system/data_pipe.h" +#include "third_party/mojo/src/mojo/public/cpp/system/data_pipe.h" namespace device {
diff --git a/device/serial/data_source_unittest.cc b/device/serial/data_source_unittest.cc index 3d96f55..71dfa81 100644 --- a/device/serial/data_source_unittest.cc +++ b/device/serial/data_source_unittest.cc
@@ -10,9 +10,9 @@ #include "device/serial/data_receiver.h" #include "device/serial/data_source_sender.h" #include "device/serial/data_stream.mojom.h" -#include "mojo/public/cpp/bindings/interface_ptr.h" -#include "mojo/public/cpp/environment/async_waiter.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_ptr.h" +#include "third_party/mojo/src/mojo/public/cpp/environment/async_waiter.h" namespace device {
diff --git a/device/serial/serial_connection.h b/device/serial/serial_connection.h index 66f9c54..d0b940f 100644 --- a/device/serial/serial_connection.h +++ b/device/serial/serial_connection.h
@@ -8,7 +8,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "device/serial/serial.mojom.h" -#include "mojo/public/cpp/bindings/interface_impl.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_impl.h" namespace device {
diff --git a/device/serial/serial_connection_factory.h b/device/serial/serial_connection_factory.h index 13b055c..4200dca 100644 --- a/device/serial/serial_connection_factory.h +++ b/device/serial/serial_connection_factory.h
@@ -12,7 +12,7 @@ #include "base/message_loop/message_loop_proxy.h" #include "device/serial/data_stream.mojom.h" #include "device/serial/serial.mojom.h" -#include "mojo/public/cpp/bindings/interface_request.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h" namespace device {
diff --git a/device/serial/serial_connection_unittest.cc b/device/serial/serial_connection_unittest.cc index 9edec433..151ed77 100644 --- a/device/serial/serial_connection_unittest.cc +++ b/device/serial/serial_connection_unittest.cc
@@ -15,10 +15,10 @@ #include "device/serial/serial_connection.h" #include "device/serial/serial_service_impl.h" #include "device/serial/test_serial_io_handler.h" -#include "mojo/public/cpp/bindings/error_handler.h" -#include "mojo/public/cpp/bindings/interface_ptr.h" -#include "mojo/public/cpp/bindings/interface_request.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/error_handler.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_ptr.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h" namespace device { namespace {
diff --git a/device/serial/serial_device_enumerator.h b/device/serial/serial_device_enumerator.h index 77e2ae5d..eeae615 100644 --- a/device/serial/serial_device_enumerator.h +++ b/device/serial/serial_device_enumerator.h
@@ -7,7 +7,7 @@ #include "base/memory/scoped_ptr.h" #include "device/serial/serial.mojom.h" -#include "mojo/public/cpp/bindings/array.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/array.h" namespace device {
diff --git a/device/serial/serial_service_impl.h b/device/serial/serial_service_impl.h index ea48e46..0caf00e 100644 --- a/device/serial/serial_service_impl.h +++ b/device/serial/serial_service_impl.h
@@ -11,7 +11,7 @@ #include "device/serial/serial.mojom.h" #include "device/serial/serial_connection_factory.h" #include "device/serial/serial_device_enumerator.h" -#include "mojo/public/cpp/bindings/interface_impl.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_impl.h" namespace device {
diff --git a/device/serial/serial_service_unittest.cc b/device/serial/serial_service_unittest.cc index 489d88e..bf08217 100644 --- a/device/serial/serial_service_unittest.cc +++ b/device/serial/serial_service_unittest.cc
@@ -8,10 +8,10 @@ #include "device/serial/serial.mojom.h" #include "device/serial/serial_service_impl.h" #include "device/serial/test_serial_io_handler.h" -#include "mojo/public/cpp/bindings/error_handler.h" -#include "mojo/public/cpp/bindings/interface_ptr.h" -#include "mojo/public/cpp/bindings/interface_request.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/error_handler.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_ptr.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h" namespace device { namespace {
diff --git a/device/test/DEPS b/device/test/DEPS index 7a97c8e5..855cb249 100644 --- a/device/test/DEPS +++ b/device/test/DEPS
@@ -1,5 +1,5 @@ include_rules = [ - "+mojo/edk/embedder", "+net/proxy", "+net/url_request", + "+third_party/mojo/src/mojo/edk/embedder", ]
diff --git a/device/test/run_all_unittests.cc b/device/test/run_all_unittests.cc index d8e2928..cfc0db3 100644 --- a/device/test/run_all_unittests.cc +++ b/device/test/run_all_unittests.cc
@@ -5,7 +5,7 @@ #include "base/bind.h" #include "base/test/launcher/unit_test_launcher.h" #include "base/test/test_suite.h" -#include "mojo/edk/embedder/test_embedder.h" +#include "third_party/mojo/src/mojo/edk/embedder/test_embedder.h" int main(int argc, char** argv) { base::TestSuite test_suite(argc, argv);
diff --git a/device/usb/usb_descriptors.h b/device/usb/usb_descriptors.h index 2881aba..0395f1d 100644 --- a/device/usb/usb_descriptors.h +++ b/device/usb/usb_descriptors.h
@@ -39,8 +39,6 @@ UsbEndpointDescriptor(); ~UsbEndpointDescriptor(); - typedef std::vector<UsbEndpointDescriptor>::const_iterator Iterator; - uint8_t address; UsbEndpointDirection direction; uint16_t maximum_packet_size; @@ -55,8 +53,6 @@ UsbInterfaceDescriptor(); ~UsbInterfaceDescriptor(); - typedef std::vector<UsbInterfaceDescriptor>::const_iterator Iterator; - uint8_t interface_number; uint8_t alternate_setting; uint8_t interface_class;
diff --git a/device/usb/usb_device_handle_impl.cc b/device/usb/usb_device_handle_impl.cc index 567a854..c64931c7 100644 --- a/device/usb/usb_device_handle_impl.cc +++ b/device/usb/usb_device_handle_impl.cc
@@ -211,6 +211,7 @@ scoped_refptr<UsbDeviceHandleImpl::InterfaceClaimer> claimed_interface_; scoped_refptr<base::SingleThreadTaskRunner> task_runner_; size_t length_; + bool cancelled_; UsbTransferCallback callback_; scoped_refptr<base::SingleThreadTaskRunner> callback_task_runner_; }; @@ -340,6 +341,7 @@ : transfer_type_(transfer_type), buffer_(buffer), length_(length), + cancelled_(false), callback_(callback) { // Remember the thread from which this transfer was created so that |callback| // can be dispatched there. @@ -376,8 +378,11 @@ } void UsbDeviceHandleImpl::Transfer::Cancel() { - libusb_cancel_transfer(platform_transfer_); - claimed_interface_ = nullptr; + if (!cancelled_) { + libusb_cancel_transfer(platform_transfer_); + claimed_interface_ = nullptr; + } + cancelled_ = true; } void UsbDeviceHandleImpl::Transfer::ProcessCompletion() {
diff --git a/extensions/DEPS b/extensions/DEPS index 1a7b60a..183bba6 100644 --- a/extensions/DEPS +++ b/extensions/DEPS
@@ -11,7 +11,7 @@ "+extensions/test", "+grit/extensions_renderer_resources.h", "+grit/extensions_resources.h", - "+mojo/public", + "+third_party/mojo/src/mojo/public", "+third_party/skia/include", "+testing",
diff --git a/extensions/browser/api/audio/audio_service_chromeos.cc b/extensions/browser/api/audio/audio_service_chromeos.cc index 99d0865..8005ac6 100644 --- a/extensions/browser/api/audio/audio_service_chromeos.cc +++ b/extensions/browser/api/audio/audio_service_chromeos.cc
@@ -22,29 +22,29 @@ public chromeos::CrasAudioHandler::AudioObserver { public: AudioServiceImpl(); - virtual ~AudioServiceImpl(); + ~AudioServiceImpl() override; // Called by listeners to this service to add/remove themselves as observers. - virtual void AddObserver(AudioService::Observer* observer) override; - virtual void RemoveObserver(AudioService::Observer* observer) override; + void AddObserver(AudioService::Observer* observer) override; + void RemoveObserver(AudioService::Observer* observer) override; // Start to query audio device information. - virtual void StartGetInfo(const GetInfoCallback& callback) override; - virtual void SetActiveDevices(const DeviceIdList& device_list) override; - virtual bool SetDeviceProperties(const std::string& device_id, - bool muted, - int volume, - int gain) override; + void StartGetInfo(const GetInfoCallback& callback) override; + void SetActiveDevices(const DeviceIdList& device_list) override; + bool SetDeviceProperties(const std::string& device_id, + bool muted, + int volume, + int gain) override; protected: // chromeos::CrasAudioHandler::AudioObserver overrides. - virtual void OnOutputVolumeChanged() override; - virtual void OnInputGainChanged() override; - virtual void OnOutputMuteChanged() override; - virtual void OnInputMuteChanged() override; - virtual void OnAudioNodesChanged() override; - virtual void OnActiveOutputNodeChanged() override; - virtual void OnActiveInputNodeChanged() override; + void OnOutputVolumeChanged() override; + void OnInputGainChanged() override; + void OnOutputMuteChanged() override; + void OnInputMuteChanged() override; + void OnAudioNodesChanged() override; + void OnActiveOutputNodeChanged() override; + void OnActiveInputNodeChanged() override; private: void NotifyDeviceChanged();
diff --git a/extensions/browser/api/cast_channel/logger.cc b/extensions/browser/api/cast_channel/logger.cc index 0e31b8f..9390210 100644 --- a/extensions/browser/api/cast_channel/logger.cc +++ b/extensions/browser/api/cast_channel/logger.cc
@@ -76,7 +76,8 @@ size_t out_size = deflateBound(&stream, input.size()); scoped_ptr<char[]> out(new char[out_size]); - COMPILE_ASSERT(sizeof(uint8) == sizeof(char), uint8_char_different_sizes); + static_assert(sizeof(uint8) == sizeof(char), + "uint8 char should be of different sizes"); stream.next_in = reinterpret_cast<uint8*>(const_cast<char*>(input.data())); stream.avail_in = input.size();
diff --git a/extensions/browser/api/declarative_webrequest/request_stage.cc b/extensions/browser/api/declarative_webrequest/request_stage.cc index c49aab44..e58e8f35 100644 --- a/extensions/browser/api/declarative_webrequest/request_stage.cc +++ b/extensions/browser/api/declarative_webrequest/request_stage.cc
@@ -17,7 +17,7 @@ // |n| is a positive compile-time constant. template <long unsigned int n> struct HighestBit { - COMPILE_ASSERT(n > 0, argument_is_not_a_positive_compile_time_constant); + static_assert(n > 0, "argument is not a positive compile time constant"); enum { VALUE = HighestBit<(n >> 1)>::VALUE << 1 }; }; template <>
diff --git a/extensions/browser/api/guest_view/guest_view_internal_api.cc b/extensions/browser/api/guest_view/guest_view_internal_api.cc index fa4201e..9e1efe5d 100644 --- a/extensions/browser/api/guest_view/guest_view_internal_api.cc +++ b/extensions/browser/api/guest_view/guest_view_internal_api.cc
@@ -79,27 +79,40 @@ return true; } -GuestViewInternalSetAutoSizeFunction:: - GuestViewInternalSetAutoSizeFunction() { +GuestViewInternalSetSizeFunction::GuestViewInternalSetSizeFunction() { } -GuestViewInternalSetAutoSizeFunction:: - ~GuestViewInternalSetAutoSizeFunction() { +GuestViewInternalSetSizeFunction::~GuestViewInternalSetSizeFunction() { } -bool GuestViewInternalSetAutoSizeFunction::RunAsync() { - scoped_ptr<guest_view_internal::SetAutoSize::Params> params( - guest_view_internal::SetAutoSize::Params::Create(*args_)); +bool GuestViewInternalSetSizeFunction::RunAsync() { + scoped_ptr<guest_view_internal::SetSize::Params> params( + guest_view_internal::SetSize::Params::Create(*args_)); EXTENSION_FUNCTION_VALIDATE(params.get()); GuestViewBase* guest = GuestViewBase::From( render_view_host()->GetProcess()->GetID(), params->instance_id); if (!guest) return false; - guest->SetAutoSize(params->params.enable_auto_size, - gfx::Size(params->params.min.width, - params->params.min.height), - gfx::Size(params->params.max.width, - params->params.max.height)); + + SetSizeParams set_size_params; + if (params->params.enable_auto_size) { + set_size_params.enable_auto_size.reset( + params->params.enable_auto_size.release()); + } + if (params->params.min) { + set_size_params.min_size.reset( + new gfx::Size(params->params.min->width, params->params.min->height)); + } + if (params->params.max) { + set_size_params.max_size.reset( + new gfx::Size(params->params.max->width, params->params.max->height)); + } + if (params->params.normal) { + set_size_params.normal_size.reset(new gfx::Size( + params->params.normal->width, params->params.normal->height)); + } + + guest->SetSize(set_size_params); SendResponse(true); return true; }
diff --git a/extensions/browser/api/guest_view/guest_view_internal_api.h b/extensions/browser/api/guest_view/guest_view_internal_api.h index 3f0b63e..3f76ab9 100644 --- a/extensions/browser/api/guest_view/guest_view_internal_api.h +++ b/extensions/browser/api/guest_view/guest_view_internal_api.h
@@ -39,19 +39,19 @@ DISALLOW_COPY_AND_ASSIGN(GuestViewInternalDestroyGuestFunction); }; -class GuestViewInternalSetAutoSizeFunction : public AsyncExtensionFunction { +class GuestViewInternalSetSizeFunction : public AsyncExtensionFunction { public: - DECLARE_EXTENSION_FUNCTION("guestViewInternal.setAutoSize", + DECLARE_EXTENSION_FUNCTION("guestViewInternal.setSize", GUESTVIEWINTERNAL_SETAUTOSIZE); - GuestViewInternalSetAutoSizeFunction(); + GuestViewInternalSetSizeFunction(); protected: - ~GuestViewInternalSetAutoSizeFunction() override; + ~GuestViewInternalSetSizeFunction() override; bool RunAsync() final; private: - DISALLOW_COPY_AND_ASSIGN(GuestViewInternalSetAutoSizeFunction); + DISALLOW_COPY_AND_ASSIGN(GuestViewInternalSetSizeFunction); }; } // namespace extensions
diff --git a/extensions/browser/api/mime_handler_private/mime_handler_private.cc b/extensions/browser/api/mime_handler_private/mime_handler_private.cc index b1f816c..e2a25b1 100644 --- a/extensions/browser/api/mime_handler_private/mime_handler_private.cc +++ b/extensions/browser/api/mime_handler_private/mime_handler_private.cc
@@ -8,8 +8,8 @@ #include "content/public/browser/stream_info.h" #include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h" #include "extensions/common/constants.h" -#include "mojo/public/cpp/bindings/map.h" #include "net/http/http_response_headers.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/map.h" namespace extensions { namespace {
diff --git a/extensions/browser/api/vpn_provider/vpn_provider_api.h b/extensions/browser/api/vpn_provider/vpn_provider_api.h index aba2280..c2384d6 100644 --- a/extensions/browser/api/vpn_provider/vpn_provider_api.h +++ b/extensions/browser/api/vpn_provider/vpn_provider_api.h
@@ -19,7 +19,7 @@ const std::string& error_message); protected: - virtual ~VpnThreadExtensionFunction(); + ~VpnThreadExtensionFunction() override; }; class VpnProviderCreateConfigFunction : public VpnThreadExtensionFunction { @@ -28,9 +28,9 @@ VPNPROVIDER_CREATECONFIG); protected: - virtual ~VpnProviderCreateConfigFunction(); + ~VpnProviderCreateConfigFunction() override; - virtual ExtensionFunction::ResponseAction Run() override; + ExtensionFunction::ResponseAction Run() override; }; class VpnProviderDestroyConfigFunction : public VpnThreadExtensionFunction { @@ -39,9 +39,9 @@ VPNPROVIDER_DESTROYCONFIG); protected: - virtual ~VpnProviderDestroyConfigFunction(); + ~VpnProviderDestroyConfigFunction() override; - virtual ExtensionFunction::ResponseAction Run() override; + ExtensionFunction::ResponseAction Run() override; }; class VpnProviderSetParametersFunction : public VpnThreadExtensionFunction { @@ -50,9 +50,9 @@ VPNPROVIDER_SETPARAMETERS); protected: - virtual ~VpnProviderSetParametersFunction(); + ~VpnProviderSetParametersFunction() override; - virtual ExtensionFunction::ResponseAction Run() override; + ExtensionFunction::ResponseAction Run() override; }; class VpnProviderSendPacketFunction : public VpnThreadExtensionFunction { @@ -60,9 +60,9 @@ DECLARE_EXTENSION_FUNCTION("vpnProvider.sendPacket", VPNPROVIDER_SENDPACKET); protected: - virtual ~VpnProviderSendPacketFunction(); + ~VpnProviderSendPacketFunction() override; - virtual ExtensionFunction::ResponseAction Run() override; + ExtensionFunction::ResponseAction Run() override; }; class VpnProviderNotifyConnectionStateChangedFunction @@ -72,9 +72,9 @@ VPNPROVIDER_NOTIFYCONNECTIONSTATECHANGED); protected: - virtual ~VpnProviderNotifyConnectionStateChangedFunction(); + ~VpnProviderNotifyConnectionStateChangedFunction() override; - virtual ExtensionFunction::ResponseAction Run() override; + ExtensionFunction::ResponseAction Run() override; }; } // namespace extensions
diff --git a/extensions/browser/api/vpn_provider/vpn_service.cc b/extensions/browser/api/vpn_provider/vpn_service.cc index f2a7efb..2ebc3ff 100644 --- a/extensions/browser/api/vpn_provider/vpn_service.cc +++ b/extensions/browser/api/vpn_provider/vpn_service.cc
@@ -59,7 +59,7 @@ const std::string& configuration_name, const std::string& key, base::WeakPtr<VpnService> vpn_service); - ~VpnConfiguration(); + ~VpnConfiguration() override; const std::string& extension_id() const { return extension_id_; } const std::string& configuration_name() const { return configuration_name_; }
diff --git a/extensions/browser/api/web_request/web_request_api.cc b/extensions/browser/api/web_request/web_request_api.cc index b04ee765..87da356 100644 --- a/extensions/browser/api/web_request/web_request_api.cc +++ b/extensions/browser/api/web_request/web_request_api.cc
@@ -458,21 +458,31 @@ RequestFilter filter; int extra_info_spec; int embedder_process_id; - int webview_instance_id; + int web_view_instance_id; base::WeakPtr<IPC::Sender> ipc_sender; mutable std::set<uint64> blocked_requests; // Comparator to work with std::set. bool operator<(const EventListener& that) const { - if (extension_id < that.extension_id) - return true; - if (extension_id == that.extension_id && - sub_event_name < that.sub_event_name) - return true; + if (extension_id != that.extension_id) + return extension_id < that.extension_id; + + if (sub_event_name != that.sub_event_name) + return sub_event_name < that.sub_event_name; + + if (embedder_process_id != that.embedder_process_id) + return embedder_process_id < that.embedder_process_id; + + if (web_view_instance_id != that.web_view_instance_id) + return web_view_instance_id < that.web_view_instance_id; + return false; } - EventListener() : extra_info_spec(0) {} + EventListener() : + extra_info_spec(0), + embedder_process_id(0), + web_view_instance_id(0) {} }; // Contains info about requests that are blocked waiting for a response from @@ -1279,7 +1289,7 @@ const RequestFilter& filter, int extra_info_spec, int embedder_process_id, - int webview_instance_id, + int web_view_instance_id, base::WeakPtr<IPC::Sender> ipc_sender) { if (!IsWebRequestEvent(event_name)) return false; @@ -1292,8 +1302,8 @@ listener.extra_info_spec = extra_info_spec; listener.ipc_sender = ipc_sender; listener.embedder_process_id = embedder_process_id; - listener.webview_instance_id = webview_instance_id; - if (listener.webview_instance_id) { + listener.web_view_instance_id = web_view_instance_id; + if (listener.web_view_instance_id) { content::RecordAction( base::UserMetricsAction("WebView.WebRequest.AddListener")); } @@ -1344,7 +1354,7 @@ void* browser_context, const std::string& extension_id, int embedder_process_id, - int webview_instance_id) { + int web_view_instance_id) { // Iterate over all listeners of all WebRequest events to delete // any listeners that belong to the provided <webview>. ListenerMapForBrowserContext& map_for_browser_context = @@ -1358,7 +1368,7 @@ listener_iter != listeners.end(); ++listener_iter) { const EventListener& listener = *listener_iter; if (listener.embedder_process_id == embedder_process_id && - listener.webview_instance_id == webview_instance_id) + listener.web_view_instance_id == web_view_instance_id) listeners_to_delete.push_back(listener); } for (size_t i = 0; i < listeners_to_delete.size(); ++i) { @@ -1482,7 +1492,7 @@ if (is_web_view_guest && (it->embedder_process_id != web_view_info.embedder_process_id || - it->webview_instance_id != web_view_info.instance_id)) + it->web_view_instance_id != web_view_info.instance_id)) continue; if (!it->filter.urls.is_empty() && !it->filter.urls.MatchesURL(url)) @@ -2205,20 +2215,21 @@ std::string sub_event_name; EXTENSION_FUNCTION_VALIDATE(args_->GetString(4, &sub_event_name)); - int webview_instance_id = 0; - EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(5, &webview_instance_id)); + int web_view_instance_id = 0; + EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(5, &web_view_instance_id)); base::WeakPtr<extensions::ExtensionMessageFilter> ipc_sender = ipc_sender_weak(); int embedder_process_id = - ipc_sender.get() ? ipc_sender->render_process_id() : -1; + ipc_sender.get() && web_view_instance_id > 0 ? + ipc_sender->render_process_id() : 0; const Extension* extension = extension_info_map()->extensions().GetByID(extension_id_safe()); std::string extension_name = extension ? extension->name() : extension_id_safe(); - if (webview_instance_id == 0) { + if (!web_view_instance_id) { // We check automatically whether the extension has the 'webRequest' // permission. For blocking calls we require the additional permission // 'webRequestBlocking'. @@ -2249,7 +2260,7 @@ ExtensionWebRequestEventRouter::GetInstance()->AddEventListener( profile_id(), extension_id_safe(), extension_name, event_name, sub_event_name, filter, extra_info_spec, - embedder_process_id, webview_instance_id, ipc_sender_weak()); + embedder_process_id, web_view_instance_id, ipc_sender_weak()); EXTENSION_FUNCTION_VALIDATE(success); helpers::ClearCacheOnNavigation();
diff --git a/extensions/browser/api/webcam_private/webcam_private_api.h b/extensions/browser/api/webcam_private/webcam_private_api.h index 05838ae..c4cef378 100644 --- a/extensions/browser/api/webcam_private/webcam_private_api.h +++ b/extensions/browser/api/webcam_private/webcam_private_api.h
@@ -17,8 +17,8 @@ DECLARE_EXTENSION_FUNCTION("webcamPrivate.set", WEBCAMPRIVATE_SET); protected: - virtual ~WebcamPrivateSetFunction(); - virtual bool RunSync() override; + ~WebcamPrivateSetFunction() override; + bool RunSync() override; private: DISALLOW_COPY_AND_ASSIGN(WebcamPrivateSetFunction); @@ -30,8 +30,8 @@ DECLARE_EXTENSION_FUNCTION("webcamPrivate.get", WEBCAMPRIVATE_GET); protected: - virtual ~WebcamPrivateGetFunction(); - virtual bool RunSync() override; + ~WebcamPrivateGetFunction() override; + bool RunSync() override; private: DISALLOW_COPY_AND_ASSIGN(WebcamPrivateGetFunction); @@ -43,8 +43,8 @@ DECLARE_EXTENSION_FUNCTION("webcamPrivate.reset", WEBCAMPRIVATE_RESET); protected: - virtual ~WebcamPrivateResetFunction(); - virtual bool RunSync() override; + ~WebcamPrivateResetFunction() override; + bool RunSync() override; private: DISALLOW_COPY_AND_ASSIGN(WebcamPrivateResetFunction);
diff --git a/extensions/browser/extension_function_histogram_value.h b/extensions/browser/extension_function_histogram_value.h index b6a4fdb..83353a1 100644 --- a/extensions/browser/extension_function_histogram_value.h +++ b/extensions/browser/extension_function_histogram_value.h
@@ -835,7 +835,7 @@ NETWORKINGPRIVATE_GETNETWORKS, DELETED_WEBVIEW_SETNAME, ENTERPRISE_PLATFORMKEYSINTERNAL_GENERATEKEY, - ENTERPRISE_PLATFORMKEYSINTERNAL_SIGN, + PLATFORMKEYSINTERNAL_SIGN, ENTERPRISE_PLATFORMKEYSINTERNAL_GETTOKENS, ENTERPRISE_PLATFORMKEYS_GETCERTIFICATES, ENTERPRISE_PLATFORMKEYS_IMPORTCERTIFICATE,
diff --git a/extensions/browser/guest_view/app_view/app_view_guest.cc b/extensions/browser/guest_view/app_view/app_view_guest.cc index afc38af..08ea9b2 100644 --- a/extensions/browser/guest_view/app_view/app_view_guest.cc +++ b/extensions/browser/guest_view/app_view/app_view_guest.cc
@@ -165,12 +165,8 @@ web_contents, security_origin, type, guest_extension); } -const char* AppViewGuest::GetAPINamespace() const { - return appview::kEmbedderAPINamespace; -} - -int AppViewGuest::GetTaskPrefix() const { - return IDS_EXTENSION_TASK_MANAGER_APPVIEW_TAG_PREFIX; +bool AppViewGuest::CanRunInDetachedState() const { + return true; } void AppViewGuest::CreateWebContents( @@ -227,22 +223,23 @@ LaunchAppAndFireEvent(make_scoped_ptr(data->DeepCopy()), callback, host); } -void AppViewGuest::DidAttachToEmbedder() { - // This is called after the guest process has been attached to a host - // element. This means that the host element knows how to route input - // events to the guest, and the guest knows how to get frames to the - // embedder. +void AppViewGuest::DidInitialize(const base::DictionaryValue& create_params) { + extension_function_dispatcher_.reset( + new ExtensionFunctionDispatcher(browser_context(), this)); + if (!url_.is_valid()) return; web_contents()->GetController().LoadURL( url_, content::Referrer(), ui::PAGE_TRANSITION_LINK, std::string()); - url_ = GURL(); } -void AppViewGuest::DidInitialize(const base::DictionaryValue& create_params) { - extension_function_dispatcher_.reset( - new ExtensionFunctionDispatcher(browser_context(), this)); +const char* AppViewGuest::GetAPINamespace() const { + return appview::kEmbedderAPINamespace; +} + +int AppViewGuest::GetTaskPrefix() const { + return IDS_EXTENSION_TASK_MANAGER_APPVIEW_TAG_PREFIX; } void AppViewGuest::OnRequest(const ExtensionHostMsg_Request_Params& params) {
diff --git a/extensions/browser/guest_view/app_view/app_view_guest.h b/extensions/browser/guest_view/app_view/app_view_guest.h index 020ed734..fa8ce8e 100644 --- a/extensions/browser/guest_view/app_view/app_view_guest.h +++ b/extensions/browser/guest_view/app_view/app_view_guest.h
@@ -52,12 +52,12 @@ content::MediaStreamType type) override; // GuestViewBase implementation. - const char* GetAPINamespace() const override; - int GetTaskPrefix() const override; + bool CanRunInDetachedState() const override; void CreateWebContents(const base::DictionaryValue& create_params, const WebContentsCreatedCallback& callback) override; - void DidAttachToEmbedder() override; void DidInitialize(const base::DictionaryValue& create_params) override; + const char* GetAPINamespace() const override; + int GetTaskPrefix() const override; // Sets the AppDelegate for this guest. void SetAppDelegateForTest(AppDelegate* delegate);
diff --git a/extensions/browser/guest_view/extension_options/extension_options_guest.cc b/extensions/browser/guest_view/extension_options/extension_options_guest.cc index 2ad00f3f..f11e2b0 100644 --- a/extensions/browser/guest_view/extension_options/extension_options_guest.cc +++ b/extensions/browser/guest_view/extension_options/extension_options_guest.cc
@@ -42,8 +42,7 @@ : GuestView<ExtensionOptionsGuest>(owner_web_contents, guest_instance_id), extension_options_guest_delegate_( extensions::ExtensionsAPIClient::Get() - ->CreateExtensionOptionsGuestDelegate(this)), - has_navigated_(false) { + ->CreateExtensionOptionsGuestDelegate(this)) { } ExtensionOptionsGuest::~ExtensionOptionsGuest() { @@ -56,6 +55,10 @@ return new ExtensionOptionsGuest(owner_web_contents, guest_instance_id); } +bool ExtensionOptionsGuest::CanRunInDetachedState() const { + return true; +} + void ExtensionOptionsGuest::CreateWebContents( const base::DictionaryValue& create_params, const WebContentsCreatedCallback& callback) { @@ -111,18 +114,6 @@ callback.Run(WebContents::Create(params)); } -void ExtensionOptionsGuest::DidAttachToEmbedder() { - // We should not re-navigate on reattachment. - if (has_navigated_) - return; - - web_contents()->GetController().LoadURL(options_page_, - content::Referrer(), - ui::PAGE_TRANSITION_LINK, - std::string()); - has_navigated_ = true; -} - void ExtensionOptionsGuest::DidInitialize( const base::DictionaryValue& create_params) { extension_function_dispatcher_.reset( @@ -130,6 +121,10 @@ if (extension_options_guest_delegate_) { extension_options_guest_delegate_->DidInitialize(); } + web_contents()->GetController().LoadURL(options_page_, + content::Referrer(), + ui::PAGE_TRANSITION_LINK, + std::string()); } void ExtensionOptionsGuest::DidStopLoading() { @@ -159,6 +154,14 @@ options.ToValue())); } +bool ExtensionOptionsGuest::IsAutoSizeSupported() const { + return true; +} + +bool ExtensionOptionsGuest::IsPreferredSizeModeEnabled() const { + return true; +} + void ExtensionOptionsGuest::OnPreferredSizeChanged(const gfx::Size& pref_size) { extension_options_internal::PreferredSizeChangedOptions options; options.width = pref_size.width(); @@ -168,14 +171,6 @@ options.ToValue())); } -bool ExtensionOptionsGuest::IsAutoSizeSupported() const { - return true; -} - -bool ExtensionOptionsGuest::IsPreferredSizeModeEnabled() const { - return true; -} - content::WebContents* ExtensionOptionsGuest::GetAssociatedWebContents() const { return web_contents(); } @@ -203,9 +198,9 @@ } void ExtensionOptionsGuest::CloseContents(content::WebContents* source) { - DispatchEventToView(new GuestViewBase::Event( - extension_options_internal::OnClose::kEventName, - make_scoped_ptr(new base::DictionaryValue()))); + DispatchEventToView( + new GuestViewBase::Event(extension_options_internal::OnClose::kEventName, + make_scoped_ptr(new base::DictionaryValue()))); } bool ExtensionOptionsGuest::HandleContextMenu(
diff --git a/extensions/browser/guest_view/extension_options/extension_options_guest.h b/extensions/browser/guest_view/extension_options/extension_options_guest.h index bc3d9292..b21aeda2 100644 --- a/extensions/browser/guest_view/extension_options/extension_options_guest.h +++ b/extensions/browser/guest_view/extension_options/extension_options_guest.h
@@ -27,9 +27,9 @@ int guest_instance_id); // GuestViewBase implementation. + bool CanRunInDetachedState() const override; void CreateWebContents(const base::DictionaryValue& create_params, const WebContentsCreatedCallback& callback) override; - void DidAttachToEmbedder() override; void DidInitialize(const base::DictionaryValue& create_params) override; void DidStopLoading() override; const char* GetAPINamespace() const override; @@ -37,8 +37,8 @@ void GuestSizeChangedDueToAutoSize(const gfx::Size& old_size, const gfx::Size& new_size) override; bool IsAutoSizeSupported() const override; - void OnPreferredSizeChanged(const gfx::Size& pref_size) override; bool IsPreferredSizeModeEnabled() const override; + void OnPreferredSizeChanged(const gfx::Size& pref_size) override; // ExtensionFunctionDispatcher::Delegate implementation. content::WebContents* GetAssociatedWebContents() const override; @@ -76,7 +76,6 @@ scoped_ptr<extensions::ExtensionOptionsGuestDelegate> extension_options_guest_delegate_; GURL options_page_; - bool has_navigated_; DISALLOW_COPY_AND_ASSIGN(ExtensionOptionsGuest); };
diff --git a/extensions/browser/guest_view/guest_view_base.cc b/extensions/browser/guest_view/guest_view_base.cc index 0560072..aaadf50 100644 --- a/extensions/browser/guest_view/guest_view_base.cc +++ b/extensions/browser/guest_view/guest_view_base.cc
@@ -53,6 +53,11 @@ } // namespace +SetSizeParams::SetSizeParams() { +} +SetSizeParams::~SetSizeParams() { +} + GuestViewBase::Event::Event(const std::string& name, scoped_ptr<base::DictionaryValue> args) : name_(name), args_(args.Pass()) { @@ -219,7 +224,7 @@ &view_instance_id_); if (CanRunInDetachedState()) - SetUpAutoSize(create_params); + SetUpSizing(create_params); // Give the derived class an opportunity to perform additional initialization. DidInitialize(create_params); @@ -239,33 +244,59 @@ DispatchEventToGuestProxy(new Event(guestview::kEventResize, args.Pass())); } -void GuestViewBase::SetAutoSize(bool enabled, - const gfx::Size& min_size, - const gfx::Size& max_size) { +void GuestViewBase::SetSize(const SetSizeParams& params) { + bool enable_auto_size = + params.enable_auto_size ? *params.enable_auto_size : auto_size_enabled_; + gfx::Size min_size = params.min_size ? *params.min_size : min_auto_size_; + gfx::Size max_size = params.max_size ? *params.max_size : max_auto_size_; + + if (params.normal_size) + normal_size_ = *params.normal_size; + min_auto_size_ = min_size; min_auto_size_.SetToMin(max_size); max_auto_size_ = max_size; max_auto_size_.SetToMax(min_size); - enabled &= !min_auto_size_.IsEmpty() && !max_auto_size_.IsEmpty() && - IsAutoSizeSupported(); - if (!enabled && !auto_size_enabled_) - return; - - auto_size_enabled_ = enabled; - - if (!attached() && !CanRunInDetachedState()) - return; + enable_auto_size &= !min_auto_size_.IsEmpty() && !max_auto_size_.IsEmpty() && + IsAutoSizeSupported(); content::RenderViewHost* rvh = web_contents()->GetRenderViewHost(); - if (auto_size_enabled_) { + if (enable_auto_size) { + // Autosize is being enabled. rvh->EnableAutoResize(min_auto_size_, max_auto_size_); + normal_size_.SetSize(0, 0); } else { - rvh->DisableAutoResize(element_size_); - DispatchOnResizeEvent(guest_size_, element_size_); - GuestSizeChangedDueToAutoSize(guest_size_, element_size_); - guest_size_ = element_size_; + // Autosize is being disabled. + // Use default width/height if missing from partially defined normal size. + if (normal_size_.width() && !normal_size_.height()) + normal_size_.set_height(guestview::kDefaultHeight); + if (!normal_size_.width() && normal_size_.height()) + normal_size_.set_width(guestview::kDefaultWidth); + + gfx::Size new_size; + if (!normal_size_.IsEmpty()) { + new_size = normal_size_; + } else if (!guest_size_.IsEmpty()) { + new_size = guest_size_; + } else { + new_size = gfx::Size(guestview::kDefaultWidth, guestview::kDefaultHeight); + } + + if (auto_size_enabled_) { + // Autosize was previously enabled. + rvh->DisableAutoResize(new_size); + GuestSizeChangedDueToAutoSize(guest_size_, new_size); + } else { + // Autosize was already disabled. + guest_sizer_->SizeContents(new_size); + } + + DispatchOnResizeEvent(guest_size_, new_size); + guest_size_ = new_size; } + + auto_size_enabled_ = enable_auto_size; } // static @@ -349,7 +380,7 @@ void GuestViewBase::DidAttach(int guest_proxy_routing_id) { opener_lifetime_observer_.reset(); - SetUpAutoSize(*attach_params()); + SetUpSizing(*attach_params()); // Give the derived class an opportunity to perform some actions. DidAttachToEmbedder(); @@ -372,26 +403,25 @@ } void GuestViewBase::ElementSizeChanged(const gfx::Size& size) { - element_size_ = size; + if (size.IsEmpty()) + return; // Only resize if needed. - if (!size.IsEmpty()) { - guest_sizer_->SizeContents(size); - guest_size_ = size; - } + guest_sizer_->SizeContents(size); + DispatchOnResizeEvent(guest_size_, size); + guest_size_ = size; } WebContents* GuestViewBase::GetOwnerWebContents() const { return owner_web_contents_; } -void GuestViewBase::GuestSizeChanged(const gfx::Size& old_size, - const gfx::Size& new_size) { - DispatchOnResizeEvent(old_size, new_size); +void GuestViewBase::GuestSizeChanged(const gfx::Size& new_size) { if (!auto_size_enabled_) return; + GuestSizeChangedDueToAutoSize(guest_size_, new_size); + DispatchOnResizeEvent(guest_size_, new_size); guest_size_ = new_size; - GuestSizeChangedDueToAutoSize(old_size, new_size); } const GURL& GuestViewBase::GetOwnerSiteURL() const { @@ -539,8 +569,8 @@ return; // Send the keyboard events back to the embedder to reprocess them. - embedder_web_contents()->GetDelegate()->HandleKeyboardEvent(web_contents(), - event); + embedder_web_contents()->GetDelegate()-> + HandleKeyboardEvent(embedder_web_contents(), event); } void GuestViewBase::RunFileChooser(WebContents* web_contents, @@ -648,7 +678,7 @@ callback.Run(guest_web_contents); } -void GuestViewBase::SetUpAutoSize(const base::DictionaryValue& params) { +void GuestViewBase::SetUpSizing(const base::DictionaryValue& params) { // Read the autosize parameters passed in from the embedder. bool auto_size_enabled = false; params.GetBoolean(guestview::kAttributeAutoSize, &auto_size_enabled); @@ -663,11 +693,22 @@ params.GetInteger(guestview::kAttributeMinHeight, &min_height); params.GetInteger(guestview::kAttributeMinWidth, &min_width); - // Call SetAutoSize to apply all the appropriate validation and clipping of + // Set the normal size to the element size so that the guestview will fit the + // element initially if autosize is disabled. + int normal_height = 0; + int normal_width = 0; + params.GetInteger(guestview::kElementHeight, &normal_height); + params.GetInteger(guestview::kElementWidth, &normal_width); + + SetSizeParams set_size_params; + set_size_params.enable_auto_size.reset(new bool(auto_size_enabled)); + set_size_params.min_size.reset(new gfx::Size(min_width, min_height)); + set_size_params.max_size.reset(new gfx::Size(max_width, max_height)); + set_size_params.normal_size.reset(new gfx::Size(normal_width, normal_height)); + + // Call SetSize to apply all the appropriate validation and clipping of // values. - SetAutoSize(auto_size_enabled, - gfx::Size(min_width, min_height), - gfx::Size(max_width, max_height)); + SetSize(set_size_params); } void GuestViewBase::StartTrackingEmbedderZoomLevel() {
diff --git a/extensions/browser/guest_view/guest_view_base.h b/extensions/browser/guest_view/guest_view_base.h index adf7ae7..e1566e8 100644 --- a/extensions/browser/guest_view/guest_view_base.h +++ b/extensions/browser/guest_view/guest_view_base.h
@@ -22,6 +22,22 @@ namespace extensions { +// A struct of parameters for SetSize(). The parameters are all declared as +// scoped pointers since they are all optional. Null pointers indicate that the +// parameter has not been provided, and the last used value should be used. Note +// that when |enable_auto_size| is true, providing |normal_size| is not +// meaningful. This is because the normal size of the guestview is overridden +// whenever autosizing occurs. +struct SetSizeParams { + SetSizeParams(); + ~SetSizeParams(); + + scoped_ptr<bool> enable_auto_size; + scoped_ptr<gfx::Size> min_size; + scoped_ptr<gfx::Size> max_size; + scoped_ptr<gfx::Size> normal_size; +}; + // A GuestViewBase is the base class browser-side API implementation for a // <*view> tag. GuestViewBase maintains an association between a guest // WebContents and an owner WebContents. It receives events issued from @@ -187,10 +203,9 @@ return !strcmp(GetViewType(), view_type); } - // Toggles autosize mode for this GuestView. - void SetAutoSize(bool enabled, - const gfx::Size& min_size, - const gfx::Size& max_size); + // Used to toggle autosize mode for this GuestView, and set both the automatic + // and normal sizes. + void SetSize(const SetSizeParams& params); bool initialized() const { return initialized_; } @@ -257,8 +272,7 @@ void DidDetach() final; void ElementSizeChanged(const gfx::Size& size) final; content::WebContents* GetOwnerWebContents() const final; - void GuestSizeChanged(const gfx::Size& old_size, - const gfx::Size& new_size) final; + void GuestSizeChanged(const gfx::Size& new_size) final; void RegisterDestructionCallback(const DestructionCallback& callback) final; void SetGuestSizer(content::GuestSizer* guest_sizer) final; void WillAttach(content::WebContents* embedder_web_contents, @@ -281,30 +295,6 @@ ~GuestViewBase() override; - private: - class OwnerLifetimeObserver; - - class OpenerLifetimeObserver; - - void DispatchEvent(Event* event, int instance_id); - - void SendQueuedEvents(); - - void CompleteInit(scoped_ptr<base::DictionaryValue> create_params, - const WebContentsCreatedCallback& callback, - content::WebContents* guest_web_contents); - - // Dispatches the onResize event to the embedder. - void DispatchOnResizeEvent(const gfx::Size& old_size, - const gfx::Size& new_size); - - void SetUpAutoSize(const base::DictionaryValue& params); - - void StartTrackingEmbedderZoomLevel(); - void StopTrackingEmbedderZoomLevel(); - - static void RegisterGuestViewTypes(); - // WebContentsObserver implementation. void DidStopLoading(content::RenderViewHost* render_view_host) final; void RenderViewReady() final; @@ -325,6 +315,30 @@ void UpdatePreferredSize(content::WebContents* web_contents, const gfx::Size& pref_size) final; + private: + class OwnerLifetimeObserver; + + class OpenerLifetimeObserver; + + void DispatchEvent(Event* event, int instance_id); + + void SendQueuedEvents(); + + void CompleteInit(scoped_ptr<base::DictionaryValue> create_params, + const WebContentsCreatedCallback& callback, + content::WebContents* guest_web_contents); + + // Dispatches the onResize event to the embedder. + void DispatchOnResizeEvent(const gfx::Size& old_size, + const gfx::Size& new_size); + + void SetUpSizing(const base::DictionaryValue& params); + + void StartTrackingEmbedderZoomLevel(); + void StopTrackingEmbedderZoomLevel(); + + static void RegisterGuestViewTypes(); + // This guest tracks the lifetime of the WebContents specified by // |owner_web_contents_|. If |owner_web_contents_| is destroyed then this // guest will also self-destruct. @@ -374,9 +388,6 @@ // away then this guest also self-destructs. scoped_ptr<OpenerLifetimeObserver> opener_lifetime_observer_; - // The size of the container element. - gfx::Size element_size_; - // The size of the guest content. Note: In autosize mode, the container // element may not match the size of the guest. gfx::Size guest_size_; @@ -393,6 +404,9 @@ // The minimum size constraints of the container element in autosize mode. gfx::Size min_auto_size_; + // The size that will be used when autosize mode is disabled. + gfx::Size normal_size_; + // Whether the guest view is inside a plugin document. bool is_full_page_plugin_;
diff --git a/extensions/browser/guest_view/web_view/web_view_apitest.cc b/extensions/browser/guest_view/web_view/web_view_apitest.cc index 01b0160..2e63b79 100644 --- a/extensions/browser/guest_view/web_view/web_view_apitest.cc +++ b/extensions/browser/guest_view/web_view/web_view_apitest.cc
@@ -390,7 +390,7 @@ RunTest("testAssignSrcAfterCrash", "web_view/apitest"); } -IN_PROC_BROWSER_TEST_F(WebViewAPITest, DISABLED_TestAutosizeAfterNavigation) { +IN_PROC_BROWSER_TEST_F(WebViewAPITest, TestAutosizeAfterNavigation) { RunTest("testAutosizeAfterNavigation", "web_view/apitest"); }
diff --git a/extensions/browser/guest_view/web_view/web_view_guest.cc b/extensions/browser/guest_view/web_view/web_view_guest.cc index 7176e10..3684daa9 100644 --- a/extensions/browser/guest_view/web_view/web_view_guest.cc +++ b/extensions/browser/guest_view/web_view/web_view_guest.cc
@@ -216,12 +216,8 @@ return guest->view_instance_id(); } -const char* WebViewGuest::GetAPINamespace() const { - return webview::kAPINamespace; -} - -int WebViewGuest::GetTaskPrefix() const { - return IDS_EXTENSION_TASK_MANAGER_WEBVIEW_TAG_PREFIX; +bool WebViewGuest::CanRunInDetachedState() const { + return true; } void WebViewGuest::CreateWebContents( @@ -303,8 +299,7 @@ // requests. PushWebViewStateToIOThread(); - // TODO(fsamuel): Once <webview> can run in a detached state, call - // ApplyAttributes here. + ApplyAttributes(create_params); } void WebViewGuest::AttachWebViewHelpers(WebContents* contents) { @@ -338,6 +333,14 @@ view_instance_id())); } +const char* WebViewGuest::GetAPINamespace() const { + return webview::kAPINamespace; +} + +int WebViewGuest::GetTaskPrefix() const { + return IDS_EXTENSION_TASK_MANAGER_WEBVIEW_TAG_PREFIX; +} + void WebViewGuest::GuestDestroyed() { // Clean up custom context menu items for this guest. if (web_view_guest_delegate_) @@ -434,20 +437,10 @@ void WebViewGuest::HandleKeyboardEvent( WebContents* source, const content::NativeWebKeyboardEvent& event) { - if (!attached()) - return; - if (HandleKeyboardShortcuts(event)) return; - // Send the unhandled keyboard events back to the embedder to reprocess them. - // TODO(fsamuel): This introduces the possibility of out-of-order keyboard - // events because the guest may be arbitrarily delayed when responding to - // keyboard events. In that time, the embedder may have received and processed - // additional key events. This needs to be fixed as soon as possible. - // See http://crbug.com/229882. - embedder_web_contents()->GetDelegate()->HandleKeyboardEvent( - web_contents(), event); + GuestViewBase::HandleKeyboardEvent(source, event); } void WebViewGuest::LoadProgressChanged(content::WebContents* source, @@ -481,10 +474,6 @@ ReportFrameNameChange(name); } -bool WebViewGuest::CanRunInDetachedState() const { - return false; -} - void WebViewGuest::CreateNewGuestWebViewWindow( const content::OpenURLParams& params) { GuestViewManager* guest_manager =
diff --git a/extensions/browser/guest_view/web_view/web_view_guest.h b/extensions/browser/guest_view/web_view/web_view_guest.h index 3c15ba3..63a1f48 100644 --- a/extensions/browser/guest_view/web_view/web_view_guest.h +++ b/extensions/browser/guest_view/web_view/web_view_guest.h
@@ -90,14 +90,15 @@ std::string* error); // GuestViewBase implementation. - const char* GetAPINamespace() const override; - int GetTaskPrefix() const override; + bool CanRunInDetachedState() const override; void CreateWebContents(const base::DictionaryValue& create_params, const WebContentsCreatedCallback& callback) override; void DidAttachToEmbedder() override; void DidInitialize(const base::DictionaryValue& create_params) override; void DidStopLoading() override; void EmbedderWillBeDestroyed() override; + const char* GetAPINamespace() const override; + int GetTaskPrefix() const override; void GuestDestroyed() override; void GuestReady() override; void GuestSizeChangedDueToAutoSize(const gfx::Size& old_size, @@ -132,6 +133,10 @@ content::WebContents* source, const content::MediaStreamRequest& request, const content::MediaResponseCallback& callback) override; + void RequestPointerLockPermission( + bool user_gesture, + bool last_unlocked_by_target, + const base::Callback<void(bool)>& callback) override; bool CheckMediaAccessPermission(content::WebContents* source, const GURL& security_origin, content::MediaStreamType type) override; @@ -160,12 +165,6 @@ const GURL& target_url, content::WebContents* new_contents) override; - // BrowserPluginGuestDelegate implementation. - bool CanRunInDetachedState() const override; - void RequestPointerLockPermission( - bool user_gesture, - bool last_unlocked_by_target, - const base::Callback<void(bool)>& callback) override; // NotificationObserver implementation. void Observe(int type, const content::NotificationSource& source,
diff --git a/extensions/browser/guest_view/web_view/web_view_renderer_state.cc b/extensions/browser/guest_view/web_view/web_view_renderer_state.cc index a58cedf..9851e617 100644 --- a/extensions/browser/guest_view/web_view/web_view_renderer_state.cc +++ b/extensions/browser/guest_view/web_view/web_view_renderer_state.cc
@@ -22,53 +22,52 @@ bool WebViewRendererState::IsGuest(int render_process_id) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - return webview_partition_id_map_.find(render_process_id) != - webview_partition_id_map_.end(); + return web_view_partition_id_map_.find(render_process_id) != + web_view_partition_id_map_.end(); } void WebViewRendererState::AddGuest(int guest_process_id, int guest_routing_id, - const WebViewInfo& webview_info) { + const WebViewInfo& web_view_info) { DCHECK_CURRENTLY_ON(BrowserThread::IO); RenderId render_id(guest_process_id, guest_routing_id); - bool updating = webview_info_map_.find(render_id) != webview_info_map_.end(); - webview_info_map_[render_id] = webview_info; + bool updating = + web_view_info_map_.find(render_id) != web_view_info_map_.end(); + web_view_info_map_[render_id] = web_view_info; if (updating) return; - WebViewPartitionIDMap::iterator iter = - webview_partition_id_map_.find(guest_process_id); - if (iter != webview_partition_id_map_.end()) { + auto iter = web_view_partition_id_map_.find(guest_process_id); + if (iter != web_view_partition_id_map_.end()) { ++iter->second.web_view_count; return; } - WebViewPartitionInfo partition_info(1, webview_info.partition_id); - webview_partition_id_map_[guest_process_id] = partition_info; + WebViewPartitionInfo partition_info(1, web_view_info.partition_id); + web_view_partition_id_map_[guest_process_id] = partition_info; } void WebViewRendererState::RemoveGuest(int guest_process_id, int guest_routing_id) { DCHECK_CURRENTLY_ON(BrowserThread::IO); RenderId render_id(guest_process_id, guest_routing_id); - webview_info_map_.erase(render_id); - WebViewPartitionIDMap::iterator iter = - webview_partition_id_map_.find(guest_process_id); - if (iter != webview_partition_id_map_.end() && + web_view_info_map_.erase(render_id); + auto iter = web_view_partition_id_map_.find(guest_process_id); + if (iter != web_view_partition_id_map_.end() && iter->second.web_view_count > 1) { --iter->second.web_view_count; return; } - webview_partition_id_map_.erase(guest_process_id); + web_view_partition_id_map_.erase(guest_process_id); } bool WebViewRendererState::GetInfo(int guest_process_id, int guest_routing_id, - WebViewInfo* webview_info) { + WebViewInfo* web_view_info) { DCHECK_CURRENTLY_ON(BrowserThread::IO); RenderId render_id(guest_process_id, guest_routing_id); - WebViewInfoMap::iterator iter = webview_info_map_.find(render_id); - if (iter != webview_info_map_.end()) { - *webview_info = iter->second; + auto iter = web_view_info_map_.find(render_id); + if (iter != web_view_info_map_.end()) { + *web_view_info = iter->second; return true; } return false; @@ -80,7 +79,7 @@ DCHECK_CURRENTLY_ON(BrowserThread::IO); // TODO(fsamuel): Store per-process info in WebViewPartitionInfo instead of in // WebViewInfo. - for (const auto& info : webview_info_map_) { + for (const auto& info : web_view_info_map_) { if (info.first.first == guest_process_id) { if (owner_process_id) *owner_process_id = info.second.embedder_process_id; @@ -95,9 +94,9 @@ bool WebViewRendererState::GetPartitionID(int guest_process_id, std::string* partition_id) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - WebViewPartitionIDMap::iterator iter = - webview_partition_id_map_.find(guest_process_id); - if (iter != webview_partition_id_map_.end()) { + + auto iter = web_view_partition_id_map_.find(guest_process_id); + if (iter != web_view_partition_id_map_.end()){ *partition_id = iter->second.partition_id; return true; }
diff --git a/extensions/browser/guest_view/web_view/web_view_renderer_state.h b/extensions/browser/guest_view/web_view/web_view_renderer_state.h index 11af76d..92882c7 100644 --- a/extensions/browser/guest_view/web_view/web_view_renderer_state.h +++ b/extensions/browser/guest_view/web_view/web_view_renderer_state.h
@@ -32,7 +32,7 @@ // Looks up the information for the embedder <webview> for a given render // view, if one exists. Called on the IO thread. bool GetInfo(int guest_process_id, int guest_routing_id, - WebViewInfo* webview_info); + WebViewInfo* web_view_info); // Looks up the information for the owner for a given guest process in a // <webview>. Called on the IO thread. @@ -51,8 +51,8 @@ friend class WebViewGuest; friend struct DefaultSingletonTraits<WebViewRendererState>; - typedef std::pair<int, int> RenderId; - typedef std::map<RenderId, WebViewInfo> WebViewInfoMap; + using RenderId = std::pair<int, int>; + using WebViewInfoMap = std::map<RenderId, WebViewInfo>; struct WebViewPartitionInfo { int web_view_count; @@ -63,18 +63,18 @@ partition_id(partition) {} }; - typedef std::map<int, WebViewPartitionInfo> WebViewPartitionIDMap; + using WebViewPartitionIDMap = std::map<int, WebViewPartitionInfo>; WebViewRendererState(); ~WebViewRendererState(); // Adds or removes a <webview> guest render process from the set. void AddGuest(int render_process_host_id, int routing_id, - const WebViewInfo& webview_info); + const WebViewInfo& web_view_info); void RemoveGuest(int render_process_host_id, int routing_id); - WebViewInfoMap webview_info_map_; - WebViewPartitionIDMap webview_partition_id_map_; + WebViewInfoMap web_view_info_map_; + WebViewPartitionIDMap web_view_partition_id_map_; DISALLOW_COPY_AND_ASSIGN(WebViewRendererState); };
diff --git a/extensions/browser/mojo/keep_alive_impl.h b/extensions/browser/mojo/keep_alive_impl.h index 0544f958..09473e2 100644 --- a/extensions/browser/mojo/keep_alive_impl.h +++ b/extensions/browser/mojo/keep_alive_impl.h
@@ -7,7 +7,7 @@ #include "base/callback.h" #include "extensions/common/mojo/keep_alive.mojom.h" -#include "mojo/public/cpp/bindings/interface_request.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h" namespace content { class BrowserContext;
diff --git a/extensions/browser/mojo/service_registration_manager.h b/extensions/browser/mojo/service_registration_manager.h index 5fed206..e57fba24 100644 --- a/extensions/browser/mojo/service_registration_manager.h +++ b/extensions/browser/mojo/service_registration_manager.h
@@ -12,7 +12,7 @@ #include "base/callback.h" #include "base/memory/linked_ptr.h" #include "content/public/common/service_registry.h" -#include "mojo/public/cpp/bindings/interface_request.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h" namespace content { class RenderFrameHost;
diff --git a/extensions/browser/mojo/stash_backend.h b/extensions/browser/mojo/stash_backend.h index b90e43d..2aff1349 100644 --- a/extensions/browser/mojo/stash_backend.h +++ b/extensions/browser/mojo/stash_backend.h
@@ -10,7 +10,7 @@ #include "base/memory/linked_ptr.h" #include "base/memory/weak_ptr.h" #include "extensions/common/mojo/stash.mojom.h" -#include "mojo/public/cpp/bindings/interface_request.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h" namespace extensions {
diff --git a/extensions/browser/warning_set.cc b/extensions/browser/warning_set.cc index 63dc550..54c1c8b 100644 --- a/extensions/browser/warning_set.cc +++ b/extensions/browser/warning_set.cc
@@ -204,7 +204,8 @@ final_parameters.push_back(base::UTF8ToUTF16(net::EscapeForHTML(message))); } - COMPILE_ASSERT(kMaxNumberOfParameters == 4u, YouNeedToAddMoreCaseStatements); + static_assert(kMaxNumberOfParameters == 4u, + "You Need To Add More Case Statements"); switch (final_parameters.size()) { case 0: return l10n_util::GetStringUTF8(message_id_);
diff --git a/extensions/common/api/guest_view_internal.json b/extensions/common/api/guest_view_internal.json index 46564e54..ddf8ce9 100644 --- a/extensions/common/api/guest_view_internal.json +++ b/extensions/common/api/guest_view_internal.json
@@ -23,18 +23,25 @@ } }, { - "id": "AutoSizeParams", + "id": "SizeParams", "type": "object", - "description": "Autosize parameters.", + "description": "Size parameters.", "properties": { "enableAutoSize": { - "type": "boolean" + "type": "boolean", + "optional": true }, "min": { - "$ref": "Size" + "$ref": "Size", + "optional": true }, "max": { - "$ref": "Size" + "$ref": "Size", + "optional": true + }, + "normal": { + "$ref": "Size", + "optional": true } } } @@ -83,7 +90,7 @@ ] }, { - "name": "setAutoSize", + "name": "setSize", "type": "function", "parameters": [ { @@ -92,7 +99,7 @@ "description": "The instance ID of the guest <webview> process. This not exposed to developers through the API." }, { - "$ref": "AutoSizeParams", + "$ref": "SizeParams", "name": "params" }, {
diff --git a/extensions/common/constants.cc b/extensions/common/constants.cc index b6eac0f..90957c0 100644 --- a/extensions/common/constants.cc +++ b/extensions/common/constants.cc
@@ -80,9 +80,9 @@ { 2 * EXTENSION_ICON_ACTION, "38", ui::SCALE_FACTOR_200P } }; -COMPILE_ASSERT(kNumExtensionActionIconSizes == - arraysize(kExtensionActionIconSizes), - num_action_icon_sizes_must_be_in_sync_with_action_icon_sizes); +static_assert(kNumExtensionActionIconSizes == + arraysize(kExtensionActionIconSizes), + "num action icon sizes must be in sync with action icon sizes"); const char kPdfExtensionId[] = "mhjfbmdgcfjbbpaeojofohoefgiehjai"; const char kQuickOfficeComponentExtensionId[] =
diff --git a/extensions/common/guest_view/guest_view_constants.cc b/extensions/common/guest_view/guest_view_constants.cc index e04e7be..3ce10726 100644 --- a/extensions/common/guest_view/guest_view_constants.cc +++ b/extensions/common/guest_view/guest_view_constants.cc
@@ -35,5 +35,7 @@ // Other. const char kGuestViewManagerKeyName[] = "guest_view_manager"; const int kInstanceIDNone = 0; +const int kDefaultWidth = 300; +const int kDefaultHeight = 300; } // namespace guestview
diff --git a/extensions/common/guest_view/guest_view_constants.h b/extensions/common/guest_view/guest_view_constants.h index d3abd3e..f42cab7d 100644 --- a/extensions/common/guest_view/guest_view_constants.h +++ b/extensions/common/guest_view/guest_view_constants.h
@@ -38,6 +38,8 @@ // Other. extern const char kGuestViewManagerKeyName[]; extern const int kInstanceIDNone; +extern const int kDefaultWidth; +extern const int kDefaultHeight; } // namespace guestview
diff --git a/extensions/common/permissions/base_set_operators.h b/extensions/common/permissions/base_set_operators.h index 38ff091..d18321ca 100644 --- a/extensions/common/permissions/base_set_operators.h +++ b/extensions/common/permissions/base_set_operators.h
@@ -69,8 +69,8 @@ BaseSetOperators() { // Ensure |T| is convertible to us, so we can safely downcast when calling // methods that must exist in |T|. - COMPILE_ASSERT((base::is_convertible<T*, BaseSetOperators<T>*>::value), - U_ptr_must_implicitly_convert_to_T_ptr); + static_assert((base::is_convertible<T*, BaseSetOperators<T>*>::value), + "U ptr must implicitly convert to T ptr"); } BaseSetOperators(const T& set) {
diff --git a/extensions/common/permissions/permission_message.h b/extensions/common/permissions/permission_message.h index fa65ab2..04570bcb 100644 --- a/extensions/common/permissions/permission_message.h +++ b/extensions/common/permissions/permission_message.h
@@ -104,8 +104,8 @@ // "ExtensionPermission2" enum in tools/metrics/histograms/histograms.xml. kEnumBoundary, }; - COMPILE_ASSERT(PermissionMessage::kNone > PermissionMessage::kUnknown, - kNone_not_greater_than_kUnknown); + static_assert(PermissionMessage::kNone > PermissionMessage::kUnknown, + "kNone should not greater than kUnknown"); // Creates the corresponding permission message. PermissionMessage(ID id, const base::string16& message);
diff --git a/extensions/common/permissions/permission_message_util.cc b/extensions/common/permissions/permission_message_util.cc index ed487f8..2358ac49 100644 --- a/extensions/common/permissions/permission_message_util.cc +++ b/extensions/common/permissions/permission_message_util.cc
@@ -86,11 +86,11 @@ IDS_EXTENSION_PROMPT_WARNING_3_HOSTS_READ_ONLY), std::make_pair(PermissionMessage::kHosts4OrMoreReadOnly, IDS_EXTENSION_PROMPT_WARNING_HOSTS_LIST_READ_ONLY)}; - COMPILE_ASSERT( + static_assert( arraysize(kReadWriteMessagesList) == arraysize(kReadOnlyMessagesList), - message_lists_different_size); - COMPILE_ASSERT(kNumMessages == arraysize(kReadWriteMessagesList), - messages_array_different_size); + "message lists should be of different size"); + static_assert(kNumMessages == arraysize(kReadWriteMessagesList), + "messages array should be of different size"); const MsgPair(&messages_list)[kNumMessages] = properties == kReadOnly ? kReadOnlyMessagesList : kReadWriteMessagesList;
diff --git a/extensions/common/url_pattern.cc b/extensions/common/url_pattern.cc index 71b522e..40142cf 100644 --- a/extensions/common/url_pattern.cc +++ b/extensions/common/url_pattern.cc
@@ -43,8 +43,8 @@ URLPattern::SCHEME_FILESYSTEM, }; -COMPILE_ASSERT(arraysize(kValidSchemes) == arraysize(kValidSchemeMasks), - must_keep_these_arrays_in_sync); +static_assert(arraysize(kValidSchemes) == arraysize(kValidSchemeMasks), + "must keep these arrays in sync"); const char kParseSuccess[] = "Success."; const char kParseErrorMissingSchemeSeparator[] = "Missing scheme separator."; @@ -69,8 +69,8 @@ kParseErrorInvalidHost, }; -COMPILE_ASSERT(URLPattern::NUM_PARSE_RESULTS == arraysize(kParseResultMessages), - must_add_message_for_each_parse_result); +static_assert(URLPattern::NUM_PARSE_RESULTS == arraysize(kParseResultMessages), + "must add message for each parse result"); const char kPathSeparator[] = "/";
diff --git a/extensions/extensions.gyp b/extensions/extensions.gyp index 6e9b3349..1197c5c 100644 --- a/extensions/extensions.gyp +++ b/extensions/extensions.gyp
@@ -1055,6 +1055,7 @@ '../content/content.gyp:content_utility', '../third_party/zlib/google/zip.gyp:zip', 'extensions_common', + 'extensions_strings.gyp:extensions_strings', ], 'include_dirs': [ '..',
diff --git a/extensions/extensions_browsertests.isolate b/extensions/extensions_browsertests.isolate new file mode 100644 index 0000000..f0381c0 --- /dev/null +++ b/extensions/extensions_browsertests.isolate
@@ -0,0 +1,69 @@ +# Copyright 2015 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. +{ + 'conditions': [ + ['OS=="linux" or OS=="mac" or OS=="win"', { + 'variables': { + 'files': [ + '../net/data/', + '../net/tools/testserver/', + '../testing/test_env.py', + '../third_party/pyftpdlib/', + '../third_party/pywebsocket/', + '../third_party/tlslite/', + '<(PRODUCT_DIR)/extensions_browsertests<(EXECUTABLE_SUFFIX)', + '<(PRODUCT_DIR)/extensions_shell_and_test.pak', + 'test/data/', + ], + }, + }], + ['OS=="linux"', { + 'variables': { + 'command': [ + '../testing/xvfb.py', + '<(PRODUCT_DIR)', + '<(PRODUCT_DIR)/extensions_browsertests<(EXECUTABLE_SUFFIX)', + '--brave-new-test-launcher', + '--test-launcher-bot-mode', + '--asan=<(asan)', + '--lsan=<(lsan)', + ], + 'files': [ + '../testing/xvfb.py', + '<(PRODUCT_DIR)/libosmesa.so', + ], + }, + }], + ['OS=="linux" and use_ozone==0', { + 'variables': { + 'files': [ + '<(PRODUCT_DIR)/xdisplaycheck<(EXECUTABLE_SUFFIX)', + ], + }, + }], + ['OS=="mac" or OS=="win"', { + 'variables': { + 'command': [ + '../testing/test_env.py', + '<(PRODUCT_DIR)/extensions_browsertests<(EXECUTABLE_SUFFIX)', + '--brave-new-test-launcher', + '--test-launcher-bot-mode', + '--asan=<(asan)', + '--lsan=<(lsan)', + ], + }, + }], + ['OS=="win" and target_arch=="ia32"', { + 'variables': { + 'files': [ + '<(PRODUCT_DIR)/wow_helper.exe', + ], + }, + }], + ], + 'includes': [ + '../base/base.isolate', + '../gin/v8.isolate', + ], +}
diff --git a/extensions/extensions_tests.gyp b/extensions/extensions_tests.gyp index aa5ad0e..0f47938 100644 --- a/extensions/extensions_tests.gyp +++ b/extensions/extensions_tests.gyp
@@ -230,4 +230,23 @@ ] }, ], + 'conditions': [ + ['test_isolation_mode != "noop"', { + 'targets': [ + { + 'target_name': 'extensions_browsertests_run', + 'type': 'none', + 'dependencies': [ + 'extensions_browsertests', + ], + 'includes': [ + '../build/isolate.gypi', + ], + 'sources': [ + 'extensions_browsertests.isolate', + ], + }, + ], + }], + ], }
diff --git a/extensions/renderer/DEPS b/extensions/renderer/DEPS index fadfee7..fcbffb6 100644 --- a/extensions/renderer/DEPS +++ b/extensions/renderer/DEPS
@@ -2,7 +2,7 @@ "+content/public/renderer", "+gin", - "+mojo/edk/js", + "+third_party/mojo/src/mojo/edk/js", "+third_party/skia/include/core",
diff --git a/extensions/renderer/api_test_base.cc b/extensions/renderer/api_test_base.cc index 6b9c837..9457df8c 100644 --- a/extensions/renderer/api_test_base.cc +++ b/extensions/renderer/api_test_base.cc
@@ -12,11 +12,11 @@ #include "extensions/renderer/process_info_native_handler.h" #include "gin/converter.h" #include "gin/dictionary.h" -#include "mojo/edk/js/core.h" -#include "mojo/edk/js/handle.h" -#include "mojo/edk/js/support.h" -#include "mojo/public/cpp/bindings/interface_request.h" -#include "mojo/public/cpp/system/core.h" +#include "third_party/mojo/src/mojo/edk/js/core.h" +#include "third_party/mojo/src/mojo/edk/js/handle.h" +#include "third_party/mojo/src/mojo/edk/js/support.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h" +#include "third_party/mojo/src/mojo/public/cpp/system/core.h" namespace extensions { namespace {
diff --git a/extensions/renderer/api_test_base.h b/extensions/renderer/api_test_base.h index 1989727..26a60a70 100644 --- a/extensions/renderer/api_test_base.h +++ b/extensions/renderer/api_test_base.h
@@ -17,9 +17,9 @@ #include "gin/modules/module_registry.h" #include "gin/object_template_builder.h" #include "gin/wrappable.h" -#include "mojo/edk/js/handle.h" -#include "mojo/public/cpp/bindings/interface_request.h" -#include "mojo/public/cpp/system/core.h" +#include "third_party/mojo/src/mojo/edk/js/handle.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h" +#include "third_party/mojo/src/mojo/public/cpp/system/core.h" namespace extensions {
diff --git a/extensions/renderer/dispatcher.cc b/extensions/renderer/dispatcher.cc index 943f1fd..ddd1c63 100644 --- a/extensions/renderer/dispatcher.cc +++ b/extensions/renderer/dispatcher.cc
@@ -82,7 +82,6 @@ #include "extensions/renderer/utils_native_handler.h" #include "extensions/renderer/v8_context_native_handler.h" #include "grit/extensions_renderer_resources.h" -#include "mojo/public/js/constants.h" #include "third_party/WebKit/public/platform/WebString.h" #include "third_party/WebKit/public/platform/WebURLRequest.h" #include "third_party/WebKit/public/web/WebCustomElement.h" @@ -93,6 +92,7 @@ #include "third_party/WebKit/public/web/WebScopedUserGesture.h" #include "third_party/WebKit/public/web/WebSecurityPolicy.h" #include "third_party/WebKit/public/web/WebView.h" +#include "third_party/mojo/src/mojo/public/js/constants.h" #include "ui/base/layout.h" #include "ui/base/resource/resource_bundle.h" #include "v8/include/v8.h"
diff --git a/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container.cc b/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container.cc index cdede3d..9c502565 100644 --- a/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container.cc +++ b/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container.cc
@@ -4,8 +4,12 @@ #include "extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container.h" +#include <map> +#include <set> + #include "content/public/renderer/render_frame.h" #include "content/public/renderer/render_view.h" +#include "content/public/renderer/v8_value_converter.h" #include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_constants.h" #include "extensions/common/extension_messages.h" #include "extensions/common/guest_view/guest_view_constants.h" @@ -71,6 +75,12 @@ // static gin::WrapperInfo ScriptableObject::kWrapperInfo = { gin::kEmbedderNativeGin }; +// Maps from content::RenderFrame to the set of MimeHandlerViewContainers within +// it. +base::LazyInstance< + std::map<content::RenderFrame*, std::set<MimeHandlerViewContainer*>>> + g_mime_handler_view_container_map = LAZY_INSTANCE_INITIALIZER; + } // namespace MimeHandlerViewContainer::MimeHandlerViewContainer( @@ -85,11 +95,27 @@ weak_factory_(this) { DCHECK(!mime_type_.empty()); is_embedded_ = !render_frame->GetWebFrame()->document().isPluginDocument(); + g_mime_handler_view_container_map.Get()[render_frame].insert(this); } MimeHandlerViewContainer::~MimeHandlerViewContainer() { if (loader_) loader_->cancel(); + + g_mime_handler_view_container_map.Get()[render_frame()].erase(this); + if (g_mime_handler_view_container_map.Get()[render_frame()].empty()) + g_mime_handler_view_container_map.Get().erase(render_frame()); +} + +// static +std::vector<MimeHandlerViewContainer*> +MimeHandlerViewContainer::FromRenderFrame(content::RenderFrame* render_frame) { + auto it = g_mime_handler_view_container_map.Get().find(render_frame); + if (it == g_mime_handler_view_container_map.Get().end()) + return std::vector<MimeHandlerViewContainer*>(); + + return std::vector<MimeHandlerViewContainer*>(it->second.begin(), + it->second.end()); } void MimeHandlerViewContainer::Ready() { @@ -126,7 +152,7 @@ OnMimeHandlerViewGuestOnLoadCompleted) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() - return handled; + return handled; } void MimeHandlerViewContainer::DidResizeElement(const gfx::Size& old_size, @@ -197,6 +223,21 @@ args); } +void MimeHandlerViewContainer::PostMessageFromValue( + const base::Value& message) { + blink::WebFrame* frame = render_frame()->GetWebFrame(); + if (!frame) + return; + + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::HandleScope handle_scope(isolate); + v8::Context::Scope context_scope(frame->mainWorldScriptContext()); + scoped_ptr<content::V8ValueConverter> converter( + content::V8ValueConverter::create()); + PostMessage(isolate, + converter->ToV8Value(&message, frame->mainWorldScriptContext())); +} + void MimeHandlerViewContainer::OnCreateMimeHandlerViewGuestACK( int element_instance_id) { DCHECK_NE(this->element_instance_id(), guestview::kInstanceIDNone); @@ -248,8 +289,7 @@ return; render_frame()->Send(new ExtensionHostMsg_CreateMimeHandlerViewGuest( - render_frame()->GetRoutingID(), - view_id_, element_instance_id(), + render_frame()->GetRoutingID(), view_id_, element_instance_id(), element_size_)); }
diff --git a/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container.h b/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container.h index 105323d..86183f1fe 100644 --- a/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container.h +++ b/extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container.h
@@ -5,6 +5,9 @@ #ifndef EXTENSIONS_RENDERER_GUEST_VIEW_MIME_HANDLER_VIEW_MIME_HANDLER_VIEW_CONTAINER_H_ #define EXTENSIONS_RENDERER_GUEST_VIEW_MIME_HANDLER_VIEW_MIME_HANDLER_VIEW_CONTAINER_H_ +#include <string> +#include <vector> + #include "base/memory/linked_ptr.h" #include "base/memory/weak_ptr.h" #include "extensions/renderer/guest_view/guest_view_container.h" @@ -41,6 +44,9 @@ const GURL& original_url); ~MimeHandlerViewContainer() override; + static std::vector<MimeHandlerViewContainer*> FromRenderFrame( + content::RenderFrame* render_frame); + // BrowserPluginDelegate implementation. void Ready() override; void DidFinishLoading() override; @@ -63,6 +69,9 @@ void PostMessage(v8::Isolate* isolate, v8::Handle<v8::Value> message); + // Post |message| to the guest. + void PostMessageFromValue(const base::Value& message); + private: // Message handlers. void OnCreateMimeHandlerViewGuestACK(int element_instance_id);
diff --git a/extensions/renderer/mojo/keep_alive_client_unittest.cc b/extensions/renderer/mojo/keep_alive_client_unittest.cc index 2e76dd3..4f23621e 100644 --- a/extensions/renderer/mojo/keep_alive_client_unittest.cc +++ b/extensions/renderer/mojo/keep_alive_client_unittest.cc
@@ -5,7 +5,7 @@ #include "extensions/common/mojo/keep_alive.mojom.h" #include "extensions/renderer/api_test_base.h" #include "grit/extensions_renderer_resources.h" -#include "mojo/public/cpp/bindings/interface_impl.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_impl.h" // A test launcher for tests for the stash client defined in // extensions/test/data/keep_alive_client_unittest.js.
diff --git a/extensions/renderer/resources/guest_view/app_view.js b/extensions/renderer/resources/guest_view/app_view.js index 4c29e9f5..17f142ba 100644 --- a/extensions/renderer/resources/guest_view/app_view.js +++ b/extensions/renderer/resources/guest_view/app_view.js
@@ -9,6 +9,9 @@ function AppViewImpl(appviewElement) { GuestViewContainer.call(this, appviewElement, 'appview'); + + this.app = ''; + this.data = ''; } AppViewImpl.prototype.__proto__ = GuestViewContainer.prototype; @@ -39,6 +42,13 @@ return this.errorNode; }; +AppViewImpl.prototype.buildContainerParams = function() { + return { + 'appId': this.app, + 'data': this.data || {} + }; +}; + AppViewImpl.prototype.connect = function(app, data, callback) { if (!this.elementAttached) { if (callback) { @@ -46,13 +56,12 @@ } return; } - var createParams = { - 'appId': app, - 'data': data || {} - }; + + this.app = app; + this.data = data; this.guest.destroy(); - this.guest.create(createParams, function() { + this.guest.create(this.buildParams(), function() { if (!this.guest.getId()) { var errorMsg = 'Unable to connect to app "' + app + '".'; window.console.warn(errorMsg);
diff --git a/extensions/renderer/resources/guest_view/guest_view.js b/extensions/renderer/resources/guest_view/guest_view.js index 1c07204..8ff4f3c5 100644 --- a/extensions/renderer/resources/guest_view/guest_view.js +++ b/extensions/renderer/resources/guest_view/guest_view.js
@@ -113,7 +113,7 @@ 'create': [null, ERROR_MSG_ALREADY_CREATED, ERROR_MSG_ALREADY_CREATED], 'destroy': [null, null, null], 'detach': [ERROR_MSG_NOT_ATTACHED, ERROR_MSG_NOT_ATTACHED, null], - 'setAutoSize': [ERROR_MSG_NOT_CREATED, null, null] + 'setSize': [ERROR_MSG_NOT_CREATED, null, null] }; // Check that the proposed action is a real action. @@ -220,6 +220,11 @@ return; } + // If this guest is attached, then detach it first. + if (!!this.internalInstanceId) { + GuestViewInternalNatives.DetachGuest(this.internalInstanceId); + } + GuestViewInternal.destroyGuest(this.id, this.handleCallback.bind(this, callback)); @@ -250,16 +255,16 @@ this.state = GUEST_STATE_CREATED; }; -// Internal implementation of setAutoSize(). -GuestViewImpl.prototype.setAutoSizeImpl = function(autoSizeParams, callback) { +// Internal implementation of setSize(). +GuestViewImpl.prototype.setSizeImpl = function(sizeParams, callback) { // Check the current state. - if (!this.checkState('setAutoSize')) { + if (!this.checkState('setSize')) { this.handleCallback(callback); return; } - GuestViewInternal.setAutoSize(this.id, autoSizeParams, - this.handleCallback.bind(this, callback)); + GuestViewInternal.setSize(this.id, sizeParams, + this.handleCallback.bind(this, callback)); }; // The exposed interface to a guestview. Exposes in its API the functions @@ -303,10 +308,10 @@ }; // Adjusts the guestview's sizing parameters. -GuestView.prototype.setAutoSize = function(autoSizeParams, callback) { +GuestView.prototype.setSize = function(sizeParams, callback) { var internal = privates(this).internal; - internal.actionQueue.push(internal.setAutoSizeImpl.bind( - internal, autoSizeParams, callback)); + internal.actionQueue.push(internal.setSizeImpl.bind( + internal, sizeParams, callback)); internal.performNextAction(); };
diff --git a/extensions/renderer/resources/guest_view/guest_view_container.js b/extensions/renderer/resources/guest_view/guest_view_container.js index 4bd7809..ad555e7c 100644 --- a/extensions/renderer/resources/guest_view/guest_view_container.js +++ b/extensions/renderer/resources/guest_view/guest_view_container.js
@@ -89,7 +89,7 @@ this.guest.attach(this.internalInstanceId, this.viewInstanceId, - this.buildAttachParams()); + this.buildParams()); return true; }; @@ -108,12 +108,20 @@ } this.guest.attach(this.internalInstanceId, this.viewInstanceId, - this.buildAttachParams()); + this.buildParams()); } }; +GuestViewContainer.prototype.buildParams = function() { + var params = this.buildContainerParams(); + params['instanceId'] = this.viewInstanceId; + params['elementWidth'] = parseInt(this.element.offsetWidth); + params['elementHeight'] = parseInt(this.element.offsetHeight); + return params; +}; + // Implemented by the specific view type, if needed. -GuestViewContainer.prototype.buildAttachParams = function() { return {}; }; +GuestViewContainer.prototype.buildContainerParams = function() { return {}; }; GuestViewContainer.prototype.handleAttributeMutation = function() {}; GuestViewContainer.prototype.onElementAttached = function() {}; GuestViewContainer.prototype.onElementDetached = function() { @@ -190,6 +198,7 @@ return; } internal.elementAttached = false; + internal.internalInstanceId = 0; internal.onElementDetached(); };
diff --git a/extensions/renderer/resources/guest_view/surface_view.js b/extensions/renderer/resources/guest_view/surface_view.js index 421aeaa..137525c4 100644 --- a/extensions/renderer/resources/guest_view/surface_view.js +++ b/extensions/renderer/resources/guest_view/surface_view.js
@@ -25,6 +25,10 @@ GuestViewContainer.forwardApiMethods(proto, apiMethods); } +SurfaceViewImpl.prototype.buildContainerParams = function() { + return { 'url': this.url }; +}; + SurfaceViewImpl.prototype.connect = function(url, callback) { if (!this.elementAttached) { if (callback) { @@ -33,13 +37,11 @@ return; } + this.url = url; + this.guest.destroy(); - var createParams = { - 'url': url - }; - - this.guest.create(createParams, function() { + this.guest.create(this.buildParams(), function() { this.attachWindow(); if (callback) { callback(true);
diff --git a/extensions/renderer/resources/guest_view/web_view.js b/extensions/renderer/resources/guest_view/web_view.js index 8ba93a7a..bc31e25 100644 --- a/extensions/renderer/resources/guest_view/web_view.js +++ b/extensions/renderer/resources/guest_view/web_view.js
@@ -74,7 +74,6 @@ this.beforeFirstNavigation = true; this.attributes[WebViewConstants.ATTRIBUTE_PARTITION].validPartitionId = true; - this.internalInstanceId = 0; }; // Sets the <webview>.request property. @@ -154,17 +153,7 @@ }; WebViewImpl.prototype.createGuest = function() { - var params = { - 'instanceId': this.viewInstanceId, - 'userAgentOverride': this.userAgentOverride, - 'width': this.element.offsetWidth, - 'height': this.element.offsetHeight, - }; - for (var i in this.attributes) { - params[i] = this.attributes[i].getValue(); - } - - this.guest.create(params, function() { + this.guest.create(this.buildParams(), function() { this.attachWindow(); }.bind(this)); }; @@ -225,7 +214,7 @@ storagePartitionId); }; -WebViewImpl.prototype.buildAttachParams = function() { +WebViewImpl.prototype.buildContainerParams = function() { var params = { 'userAgentOverride': this.userAgentOverride }; for (var i in this.attributes) { params[i] = this.attributes[i].getValue();
diff --git a/extensions/renderer/resources/guest_view/web_view_attributes.js b/extensions/renderer/resources/guest_view/web_view_attributes.js index 101e1665..f8077b9 100644 --- a/extensions/renderer/resources/guest_view/web_view_attributes.js +++ b/extensions/renderer/resources/guest_view/web_view_attributes.js
@@ -108,7 +108,7 @@ if (!this.webViewImpl.guest.getId()) { return; } - this.webViewImpl.guest.setAutoSize({ + this.webViewImpl.guest.setSize({ 'enableAutoSize': this.webViewImpl.attributes[ WebViewConstants.ATTRIBUTE_AUTOSIZE].getValue(), 'min': {
diff --git a/extensions/renderer/resources/last_error.js b/extensions/renderer/resources/last_error.js index 8d53371..9b5b3c0 100644 --- a/extensions/renderer/resources/last_error.js +++ b/extensions/renderer/resources/last_error.js
@@ -19,12 +19,12 @@ * optional |stack|. */ function set(name, message, stack, targetChrome) { - var errorMessage = name + ': ' + message; - if (stack != null && stack != '') - errorMessage += '\n' + stack; - - if (!targetChrome) + if (!targetChrome) { + var errorMessage = name + ': ' + message; + if (stack != null && stack != '') + errorMessage += '\n' + stack; throw new Error('No chrome object to set error: ' + errorMessage); + } clear(targetChrome); // in case somebody has set a sneaky getter/setter var errorObject = { message: message }; @@ -113,12 +113,30 @@ try { $Function.apply(callback, undefined, args); } finally { + reportIfUnchecked(name, targetChrome, stack); clear(targetChrome); } } +/** + * Checks whether chrome.runtime.lastError has been accessed if set. + * If it was set but not accessed, the error is reported to the console. + * + * @param {string=} name - name of API. + * @param {Object} targetChrome - the Chrome object to check. + * @param {string=} stack - Stack trace of the call up to the error. + */ +function reportIfUnchecked(name, targetChrome, stack) { + if (hasAccessed(targetChrome) || !hasError(targetChrome)) + return; + var message = targetChrome.runtime.lastError.message; + console.error("Unchecked runtime.lastError while running " + + (name || "unknown") + ": " + message + (stack ? "\n" + stack : "")); +} + exports.clear = clear; exports.hasAccessed = hasAccessed; exports.hasError = hasError; exports.set = set; exports.run = run; +exports.reportIfUnchecked = reportIfUnchecked;
diff --git a/extensions/renderer/resources/send_request.js b/extensions/renderer/resources/send_request.js index 7cdc7d16..bdf0324a 100644 --- a/extensions/renderer/resources/send_request.js +++ b/extensions/renderer/resources/send_request.js
@@ -73,15 +73,10 @@ safeCallbackApply(name, request, request.callback, responseList); } - if (error && - !lastError.hasAccessed(chrome) && - !lastError.hasAccessed(callerChrome)) { - // The native call caused an error, but the developer didn't check - // runtime.lastError. - // Notify the developer of the error via the (error) console. - console.error("Unchecked runtime.lastError while running " + - (name || "unknown") + ": " + error + - (request.stack ? "\n" + request.stack : "")); + if (error && !lastError.hasAccessed(chrome)) { + // The native call caused an error, but the developer might not have + // checked runtime.lastError. + lastError.reportIfUnchecked(name, callerChrome, request.stack); } } finally { delete requests[requestId]; @@ -120,12 +115,14 @@ // - forIOThread: true if this function should be handled on the browser IO // thread. // - preserveNullInObjects: true if it is safe for null to be in objects. +// - stack: An optional string that contains the stack trace, to be displayed +// to the user if an error occurs. function sendRequest(functionName, args, argSchemas, optArgs) { calledSendRequest = true; if (!optArgs) optArgs = {}; var request = prepareRequest(args, argSchemas); - request.stack = exceptionHandler.getExtensionStackTrace(); + request.stack = optArgs.stack || exceptionHandler.getExtensionStackTrace(); if (optArgs.customCallback) { request.customCallback = optArgs.customCallback; }
diff --git a/extensions/shell/browser/shell_audio_controller_chromeos.h b/extensions/shell/browser/shell_audio_controller_chromeos.h index 4edeff8..c8b9646b 100644 --- a/extensions/shell/browser/shell_audio_controller_chromeos.h +++ b/extensions/shell/browser/shell_audio_controller_chromeos.h
@@ -14,7 +14,7 @@ class ShellAudioController : public chromeos::CrasAudioHandler::AudioObserver { public: ShellAudioController(); - virtual ~ShellAudioController(); + ~ShellAudioController() override; // chromeos::CrasAudioHandler::Observer implementation: void OnOutputVolumeChanged() override;
diff --git a/extensions/shell/browser/shell_audio_controller_chromeos_unittest.cc b/extensions/shell/browser/shell_audio_controller_chromeos_unittest.cc index 95d54f5d5..a1563c7 100644 --- a/extensions/shell/browser/shell_audio_controller_chromeos_unittest.cc +++ b/extensions/shell/browser/shell_audio_controller_chromeos_unittest.cc
@@ -36,7 +36,7 @@ controller_.reset(new ShellAudioController()); } - virtual ~ShellAudioControllerTest() { + ~ShellAudioControllerTest() override { controller_.reset(); chromeos::CrasAudioHandler::Shutdown(); chromeos::DBusThreadManager::Shutdown();
diff --git a/extensions/shell/browser/shell_network_controller_chromeos.h b/extensions/shell/browser/shell_network_controller_chromeos.h index 385de90..1f36a744 100644 --- a/extensions/shell/browser/shell_network_controller_chromeos.h +++ b/extensions/shell/browser/shell_network_controller_chromeos.h
@@ -23,11 +23,11 @@ // This class must be instantiated after chromeos::DBusThreadManager and // destroyed before it. explicit ShellNetworkController(const std::string& preferred_network_name); - virtual ~ShellNetworkController(); + ~ShellNetworkController() override; // chromeos::NetworkStateHandlerObserver overrides: - virtual void NetworkListChanged() override; - virtual void NetworkConnectionStateChanged( + void NetworkListChanged() override; + void NetworkConnectionStateChanged( const chromeos::NetworkState* state) override; private:
diff --git a/extensions/test/DEPS b/extensions/test/DEPS index 27ef4ea..b334588 100644 --- a/extensions/test/DEPS +++ b/extensions/test/DEPS
@@ -1,5 +1,5 @@ include_rules = [ "+content/public", - "+mojo/edk/embedder", + "+third_party/mojo/src/mojo/edk/embedder", "+ui/gl", ]
diff --git a/extensions/test/data/web_view/apitest/main.js b/extensions/test/data/web_view/apitest/main.js index 4cdcc50..4495ed4 100644 --- a/extensions/test/data/web_view/apitest/main.js +++ b/extensions/test/data/web_view/apitest/main.js
@@ -165,6 +165,8 @@ var webview = document.createElement('webview'); var step = 1; + var autosizeWidth = -1; + var autosizeHeight = -1; var sizeChangeHandler = function(e) { switch (step) { case 1: @@ -174,14 +176,15 @@ embedder.test.assertTrue(e.newWidth >= 60 && e.newWidth <= 70); embedder.test.assertTrue(e.newHeight >= 110 && e.newHeight <= 120); - // Remove autosize attribute and expect webview to return to its - // original size. + // Remove autosize attribute and expect webview to retain the same size. + autosizeWidth = e.newWidth; + autosizeHeight = e.newHeight; webview.removeAttribute('autosize'); break; case 2: - // Expect 50x100. - embedder.test.assertEq(50, e.newWidth); - embedder.test.assertEq(100, e.newHeight); + // Expect the autosized size. + embedder.test.assertEq(autosizeWidth, e.newWidth); + embedder.test.assertEq(autosizeHeight, e.newHeight); embedder.test.succeed(); break;
diff --git a/extensions/test/extensions_unittests_main.cc b/extensions/test/extensions_unittests_main.cc index cdf926a..9452f31b3 100644 --- a/extensions/test/extensions_unittests_main.cc +++ b/extensions/test/extensions_unittests_main.cc
@@ -13,7 +13,7 @@ #include "extensions/common/constants.h" #include "extensions/common/extension_paths.h" #include "extensions/test/test_extensions_client.h" -#include "mojo/edk/embedder/test_embedder.h" +#include "third_party/mojo/src/mojo/edk/embedder/test_embedder.h" #include "ui/base/resource/resource_bundle.h" #include "ui/gl/gl_surface.h"
diff --git a/gin/isolate_holder.cc b/gin/isolate_holder.cc index c666e29..21598a8 100644 --- a/gin/isolate_holder.cc +++ b/gin/isolate_holder.cc
@@ -10,6 +10,7 @@ #include "base/files/memory_mapped_file.h" #include "base/logging.h" #include "base/message_loop/message_loop.h" +#include "base/metrics/field_trial.h" #include "base/rand_util.h" #include "base/strings/sys_string_conversions.h" #include "base/sys_info.h" @@ -266,8 +267,12 @@ v8::V8::SetArrayBufferAllocator(allocator); g_array_buffer_allocator = allocator; if (mode == gin::IsolateHolder::kStrictMode) { - static const char v8_flags[] = "--use_strict"; - v8::V8::SetFlagsFromString(v8_flags, sizeof(v8_flags) - 1); + static const char use_strict[] = "--use_strict"; + v8::V8::SetFlagsFromString(use_strict, sizeof(use_strict) - 1); + } + if (base::FieldTrialList::FindFullName("V8VerifyHeap") == "Enabled") { + static const char verify_heap[] = "--verify_heap"; + v8::V8::SetFlagsFromString(verify_heap, sizeof(verify_heap) - 1); } v8::V8::SetEntropySource(&GenerateEntropy); #if defined(V8_USE_EXTERNAL_STARTUP_DATA)
diff --git a/google_apis/BUILD.gn b/google_apis/BUILD.gn index b07feb7..cbc483a5 100644 --- a/google_apis/BUILD.gn +++ b/google_apis/BUILD.gn
@@ -153,12 +153,8 @@ "drive/drive_common_callbacks.h", "drive/gdata_errorcode.cc", "drive/gdata_errorcode.h", - "drive/gdata_wapi_requests.cc", - "drive/gdata_wapi_requests.h", "drive/gdata_wapi_parser.cc", "drive/gdata_wapi_parser.h", - "drive/gdata_wapi_url_generator.cc", - "drive/gdata_wapi_url_generator.h", "drive/request_sender.cc", "drive/request_sender.h", "drive/request_util.cc", @@ -236,9 +232,6 @@ "drive/drive_api_parser_unittest.cc", "drive/drive_api_requests_unittest.cc", "drive/drive_api_url_generator_unittest.cc", - "drive/gdata_wapi_parser_unittest.cc", - "drive/gdata_wapi_requests_unittest.cc", - "drive/gdata_wapi_url_generator_unittest.cc", "drive/request_sender_unittest.cc", "drive/request_util_unittest.cc", "drive/time_util_unittest.cc",
diff --git a/google_apis/drive/drive_common_callbacks.h b/google_apis/drive/drive_common_callbacks.h index 234c531..db2a7ae 100644 --- a/google_apis/drive/drive_common_callbacks.h +++ b/google_apis/drive/drive_common_callbacks.h
@@ -14,18 +14,6 @@ class AboutResource; class AppList; -class ResourceEntry; -class ResourceList; - -// Callback used for getting ResourceList. -typedef base::Callback<void(GDataErrorCode error, - scoped_ptr<ResourceList> resource_list)> - GetResourceListCallback; - -// Callback used for getting ResourceEntry. -typedef base::Callback<void(GDataErrorCode error, - scoped_ptr<ResourceEntry> entry)> - GetResourceEntryCallback; // Callback used for getting AboutResource. typedef base::Callback<void(GDataErrorCode error,
diff --git a/google_apis/drive/gdata_wapi_parser.cc b/google_apis/drive/gdata_wapi_parser.cc index 83beacc3..d0c6a57 100644 --- a/google_apis/drive/gdata_wapi_parser.cc +++ b/google_apis/drive/gdata_wapi_parser.cc
@@ -4,560 +4,17 @@ #include "google_apis/drive/gdata_wapi_parser.h" -#include <algorithm> -#include <string> - -#include "base/basictypes.h" -#include "base/files/file_path.h" -#include "base/json/json_value_converter.h" -#include "base/memory/scoped_ptr.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_piece.h" -#include "base/strings/string_util.h" -#include "base/strings/utf_string_conversions.h" -#include "base/values.h" -#include "google_apis/drive/time_util.h" - -using base::Value; -using base::DictionaryValue; -using base::ListValue; - namespace google_apis { -namespace { - -// Term values for kSchemeKind category: -const char kTermPrefix[] = "http://schemas.google.com/docs/2007#"; - -// Node names. -const char kEntryNode[] = "entry"; - -// Field names. -const char kAuthorField[] = "author"; -const char kCategoryField[] = "category"; -const char kChangestampField[] = "docs$changestamp.value"; -const char kContentField[] = "content"; -const char kDeletedField[] = "gd$deleted"; -const char kETagField[] = "gd$etag"; -const char kEmailField[] = "email.$t"; -const char kEntryField[] = "entry"; -const char kFeedField[] = "feed"; -const char kFeedLinkField[] = "gd$feedLink"; -const char kFileNameField[] = "docs$filename.$t"; -const char kHrefField[] = "href"; -const char kIDField[] = "id.$t"; -const char kItemsPerPageField[] = "openSearch$itemsPerPage.$t"; -const char kLabelField[] = "label"; -const char kLargestChangestampField[] = "docs$largestChangestamp.value"; -const char kLastViewedField[] = "gd$lastViewed.$t"; -const char kLinkField[] = "link"; -const char kMD5Field[] = "docs$md5Checksum.$t"; -const char kNameField[] = "name.$t"; -const char kPublishedField[] = "published.$t"; -const char kRelField[] = "rel"; -const char kRemovedField[] = "docs$removed"; -const char kResourceIdField[] = "gd$resourceId.$t"; -const char kSchemeField[] = "scheme"; -const char kSizeField[] = "docs$size.$t"; -const char kSrcField[] = "src"; -const char kStartIndexField[] = "openSearch$startIndex.$t"; -const char kSuggestedFileNameField[] = "docs$suggestedFilename.$t"; -const char kTermField[] = "term"; -const char kTitleField[] = "title"; -const char kTitleTField[] = "title.$t"; -const char kTypeField[] = "type"; -const char kUpdatedField[] = "updated.$t"; - -// Link Prefixes -const char kOpenWithPrefix[] = "http://schemas.google.com/docs/2007#open-with-"; -const size_t kOpenWithPrefixSize = arraysize(kOpenWithPrefix) - 1; - -struct LinkTypeMap { - Link::LinkType type; - const char* rel; -}; - -const LinkTypeMap kLinkTypeMap[] = { - { Link::LINK_SELF, - "self" }, - { Link::LINK_NEXT, - "next" }, - { Link::LINK_PARENT, - "http://schemas.google.com/docs/2007#parent" }, - { Link::LINK_ALTERNATE, - "alternate"}, - { Link::LINK_EDIT, - "edit" }, - { Link::LINK_EDIT_MEDIA, - "edit-media" }, - { Link::LINK_ALT_EDIT_MEDIA, - "http://schemas.google.com/docs/2007#alt-edit-media" }, - { Link::LINK_ALT_POST, - "http://schemas.google.com/docs/2007#alt-post" }, - { Link::LINK_FEED, - "http://schemas.google.com/g/2005#feed"}, - { Link::LINK_POST, - "http://schemas.google.com/g/2005#post"}, - { Link::LINK_BATCH, - "http://schemas.google.com/g/2005#batch"}, - { Link::LINK_THUMBNAIL, - "http://schemas.google.com/docs/2007/thumbnail"}, - { Link::LINK_RESUMABLE_EDIT_MEDIA, - "http://schemas.google.com/g/2005#resumable-edit-media"}, - { Link::LINK_RESUMABLE_CREATE_MEDIA, - "http://schemas.google.com/g/2005#resumable-create-media"}, - { Link::LINK_TABLES_FEED, - "http://schemas.google.com/spreadsheets/2006#tablesfeed"}, - { Link::LINK_WORKSHEET_FEED, - "http://schemas.google.com/spreadsheets/2006#worksheetsfeed"}, - { Link::LINK_EMBED, - "http://schemas.google.com/docs/2007#embed"}, - { Link::LINK_PRODUCT, - "http://schemas.google.com/docs/2007#product"}, - { Link::LINK_ICON, - "http://schemas.google.com/docs/2007#icon"}, - { Link::LINK_SHARE, - "http://schemas.google.com/docs/2007#share"}, -}; - -struct ResourceLinkTypeMap { - ResourceLink::ResourceLinkType type; - const char* rel; -}; - -const ResourceLinkTypeMap kFeedLinkTypeMap[] = { - { ResourceLink::FEED_LINK_ACL, - "http://schemas.google.com/acl/2007#accessControlList" }, - { ResourceLink::FEED_LINK_REVISIONS, - "http://schemas.google.com/docs/2007/revisions" }, -}; - -struct CategoryTypeMap { - Category::CategoryType type; - const char* scheme; -}; - -const CategoryTypeMap kCategoryTypeMap[] = { - { Category::CATEGORY_KIND, "http://schemas.google.com/g/2005#kind" }, - { Category::CATEGORY_LABEL, "http://schemas.google.com/g/2005/labels" }, -}; - -// Converts |url_string| to |result|. Always returns true to be used -// for JSONValueConverter::RegisterCustomField method. -// TODO(mukai): make it return false in case of invalid |url_string|. -bool GetGURLFromString(const base::StringPiece& url_string, GURL* result) { - *result = GURL(url_string.as_string()); - return true; -} - -} // namespace - -//////////////////////////////////////////////////////////////////////////////// -// Author implementation - -Author::Author() { -} - -// static -void Author::RegisterJSONConverter( - base::JSONValueConverter<Author>* converter) { - converter->RegisterStringField(kNameField, &Author::name_); - converter->RegisterStringField(kEmailField, &Author::email_); -} - -//////////////////////////////////////////////////////////////////////////////// -// Link implementation - -Link::Link() : type_(Link::LINK_UNKNOWN) { -} - -Link::~Link() { -} - -// static -bool Link::GetAppID(const base::StringPiece& rel, std::string* app_id) { - DCHECK(app_id); - // Fast return path if the link clearly isn't an OPEN_WITH link. - if (rel.size() < kOpenWithPrefixSize) { - app_id->clear(); - return true; - } - - const std::string kOpenWithPrefixStr(kOpenWithPrefix); - if (StartsWithASCII(rel.as_string(), kOpenWithPrefixStr, false)) { - *app_id = rel.as_string().substr(kOpenWithPrefixStr.size()); - return true; - } - - app_id->clear(); - return true; -} - -// static. -bool Link::GetLinkType(const base::StringPiece& rel, Link::LinkType* type) { - DCHECK(type); - for (size_t i = 0; i < arraysize(kLinkTypeMap); i++) { - if (rel == kLinkTypeMap[i].rel) { - *type = kLinkTypeMap[i].type; - return true; - } - } - - // OPEN_WITH links have extra information at the end of the rel that is unique - // for each one, so we can't just check the usual map. This check is slightly - // redundant to provide a quick skip if it's obviously not an OPEN_WITH url. - if (rel.size() >= kOpenWithPrefixSize && - StartsWithASCII(rel.as_string(), kOpenWithPrefix, false)) { - *type = LINK_OPEN_WITH; - return true; - } - - // Let unknown link types through, just report it; if the link type is needed - // in the future, add it into LinkType and kLinkTypeMap. - DVLOG(1) << "Ignoring unknown link type for rel " << rel; - *type = LINK_UNKNOWN; - return true; -} - -// static -void Link::RegisterJSONConverter(base::JSONValueConverter<Link>* converter) { - converter->RegisterCustomField<Link::LinkType>(kRelField, - &Link::type_, - &Link::GetLinkType); - // We have to register kRelField twice because we extract two different pieces - // of data from the same rel field. - converter->RegisterCustomField<std::string>(kRelField, - &Link::app_id_, - &Link::GetAppID); - converter->RegisterCustomField(kHrefField, &Link::href_, &GetGURLFromString); - converter->RegisterStringField(kTitleField, &Link::title_); - converter->RegisterStringField(kTypeField, &Link::mime_type_); -} - -//////////////////////////////////////////////////////////////////////////////// -// ResourceLink implementation - -ResourceLink::ResourceLink() : type_(ResourceLink::FEED_LINK_UNKNOWN) { -} - -// static. -bool ResourceLink::GetFeedLinkType( - const base::StringPiece& rel, ResourceLink::ResourceLinkType* result) { - for (size_t i = 0; i < arraysize(kFeedLinkTypeMap); i++) { - if (rel == kFeedLinkTypeMap[i].rel) { - *result = kFeedLinkTypeMap[i].type; - return true; - } - } - DVLOG(1) << "Unknown feed link type for rel " << rel; - return false; -} - -// static -void ResourceLink::RegisterJSONConverter( - base::JSONValueConverter<ResourceLink>* converter) { - converter->RegisterCustomField<ResourceLink::ResourceLinkType>( - kRelField, &ResourceLink::type_, &ResourceLink::GetFeedLinkType); - converter->RegisterCustomField( - kHrefField, &ResourceLink::href_, &GetGURLFromString); -} - -//////////////////////////////////////////////////////////////////////////////// -// Category implementation - -Category::Category() : type_(CATEGORY_UNKNOWN) { -} - -// Converts category.scheme into CategoryType enum. -bool Category::GetCategoryTypeFromScheme( - const base::StringPiece& scheme, Category::CategoryType* result) { - for (size_t i = 0; i < arraysize(kCategoryTypeMap); i++) { - if (scheme == kCategoryTypeMap[i].scheme) { - *result = kCategoryTypeMap[i].type; - return true; - } - } - DVLOG(1) << "Unknown feed link type for scheme " << scheme; - return false; -} - -// static -void Category::RegisterJSONConverter( - base::JSONValueConverter<Category>* converter) { - converter->RegisterStringField(kLabelField, &Category::label_); - converter->RegisterCustomField<Category::CategoryType>( - kSchemeField, &Category::type_, &Category::GetCategoryTypeFromScheme); - converter->RegisterStringField(kTermField, &Category::term_); -} - -const Link* CommonMetadata::GetLinkByType(Link::LinkType type) const { - for (size_t i = 0; i < links_.size(); ++i) { - if (links_[i]->type() == type) - return links_[i]; - } - return NULL; -} - -//////////////////////////////////////////////////////////////////////////////// -// Content implementation - -Content::Content() { -} - -// static -void Content::RegisterJSONConverter( - base::JSONValueConverter<Content>* converter) { - converter->RegisterCustomField(kSrcField, &Content::url_, &GetGURLFromString); - converter->RegisterStringField(kTypeField, &Content::mime_type_); -} - -//////////////////////////////////////////////////////////////////////////////// -// CommonMetadata implementation - -CommonMetadata::CommonMetadata() { -} - -CommonMetadata::~CommonMetadata() { -} - -// static -template<typename CommonMetadataDescendant> -void CommonMetadata::RegisterJSONConverter( - base::JSONValueConverter<CommonMetadataDescendant>* converter) { - converter->RegisterStringField(kETagField, &CommonMetadata::etag_); - converter->template RegisterRepeatedMessage<Author>( - kAuthorField, &CommonMetadata::authors_); - converter->template RegisterRepeatedMessage<Link>( - kLinkField, &CommonMetadata::links_); - converter->template RegisterRepeatedMessage<Category>( - kCategoryField, &CommonMetadata::categories_); - converter->template RegisterCustomField<base::Time>( - kUpdatedField, &CommonMetadata::updated_time_, &util::GetTimeFromString); -} - //////////////////////////////////////////////////////////////////////////////// // ResourceEntry implementation ResourceEntry::ResourceEntry() : kind_(ENTRY_KIND_UNKNOWN), - file_size_(0), - deleted_(false), - removed_(false), - changestamp_(0), - image_width_(-1), - image_height_(-1), - image_rotation_(-1) { + deleted_(false) { } ResourceEntry::~ResourceEntry() { } -bool ResourceEntry::HasFieldPresent(const base::Value* value, - bool* result) { - *result = (value != NULL); - return true; -} - -bool ResourceEntry::ParseChangestamp(const base::Value* value, - int64* result) { - DCHECK(result); - if (!value) { - *result = 0; - return true; - } - - std::string string_value; - if (value->GetAsString(&string_value) && - base::StringToInt64(string_value, result)) - return true; - - return false; -} - -// static -void ResourceEntry::RegisterJSONConverter( - base::JSONValueConverter<ResourceEntry>* converter) { - // Inherit the parent registrations. - CommonMetadata::RegisterJSONConverter(converter); - converter->RegisterStringField( - kResourceIdField, &ResourceEntry::resource_id_); - converter->RegisterStringField(kIDField, &ResourceEntry::id_); - converter->RegisterStringField(kTitleTField, &ResourceEntry::title_); - converter->RegisterCustomField<base::Time>( - kPublishedField, &ResourceEntry::published_time_, - &util::GetTimeFromString); - converter->RegisterCustomField<base::Time>( - kLastViewedField, &ResourceEntry::last_viewed_time_, - &util::GetTimeFromString); - converter->RegisterRepeatedMessage( - kFeedLinkField, &ResourceEntry::resource_links_); - converter->RegisterNestedField(kContentField, &ResourceEntry::content_); - - // File properties. If the resource type is not a normal file, then - // that's no problem because those feed must not have these fields - // themselves, which does not report errors. - converter->RegisterStringField(kFileNameField, &ResourceEntry::filename_); - converter->RegisterStringField(kMD5Field, &ResourceEntry::file_md5_); - converter->RegisterCustomField<int64>( - kSizeField, &ResourceEntry::file_size_, &base::StringToInt64); - converter->RegisterStringField( - kSuggestedFileNameField, &ResourceEntry::suggested_filename_); - // Deleted are treated as 'trashed' items on web client side. Removed files - // are gone for good. We treat both cases as 'deleted' for this client. - converter->RegisterCustomValueField<bool>( - kDeletedField, &ResourceEntry::deleted_, &ResourceEntry::HasFieldPresent); - converter->RegisterCustomValueField<bool>( - kRemovedField, &ResourceEntry::removed_, &ResourceEntry::HasFieldPresent); - converter->RegisterCustomValueField<int64>( - kChangestampField, &ResourceEntry::changestamp_, - &ResourceEntry::ParseChangestamp); - // ImageMediaMetadata fields are not supported by WAPI. -} - -// static -ResourceEntry::ResourceEntryKind ResourceEntry::GetEntryKindFromTerm( - const std::string& term) { - if (!StartsWithASCII(term, kTermPrefix, false)) { - DVLOG(1) << "Unexpected term prefix term " << term; - return ENTRY_KIND_UNKNOWN; - } - - std::string type = term.substr(strlen(kTermPrefix)); - if (type == "folder") - return ENTRY_KIND_FOLDER; - if (type == "file" || type == "pdf") - return ENTRY_KIND_FILE; - - DVLOG(1) << "Unknown entry type for term " << term << ", type " << type; - return ENTRY_KIND_UNKNOWN; -} - -void ResourceEntry::FillRemainingFields() { - // Set |kind_| and |labels_| based on the |categories_| in the class. - // JSONValueConverter does not have the ability to catch an element in a list - // based on a predicate. Thus we need to iterate over |categories_| and - // find the elements to set these fields as a post-process. - for (size_t i = 0; i < categories_.size(); ++i) { - const Category* category = categories_[i]; - if (category->type() == Category::CATEGORY_KIND) - kind_ = GetEntryKindFromTerm(category->term()); - else if (category->type() == Category::CATEGORY_LABEL) - labels_.push_back(category->label()); - } -} - -// static -scoped_ptr<ResourceEntry> ResourceEntry::ExtractAndParse( - const base::Value& value) { - const base::DictionaryValue* as_dict = NULL; - const base::DictionaryValue* entry_dict = NULL; - if (value.GetAsDictionary(&as_dict) && - as_dict->GetDictionary(kEntryField, &entry_dict)) { - return ResourceEntry::CreateFrom(*entry_dict); - } - return scoped_ptr<ResourceEntry>(); -} - -// static -scoped_ptr<ResourceEntry> ResourceEntry::CreateFrom(const base::Value& value) { - base::JSONValueConverter<ResourceEntry> converter; - scoped_ptr<ResourceEntry> entry(new ResourceEntry()); - if (!converter.Convert(value, entry.get())) { - DVLOG(1) << "Invalid resource entry!"; - return scoped_ptr<ResourceEntry>(); - } - - entry->FillRemainingFields(); - return entry.Pass(); -} - -// static -std::string ResourceEntry::GetEntryNodeName() { - return kEntryNode; -} - -//////////////////////////////////////////////////////////////////////////////// -// ResourceList implementation - -ResourceList::ResourceList() - : start_index_(0), - items_per_page_(0), - largest_changestamp_(0) { -} - -ResourceList::~ResourceList() { -} - -// static -void ResourceList::RegisterJSONConverter( - base::JSONValueConverter<ResourceList>* converter) { - // inheritance - CommonMetadata::RegisterJSONConverter(converter); - // TODO(zelidrag): Once we figure out where these will be used, we should - // check for valid start_index_ and items_per_page_ values. - converter->RegisterCustomField<int>( - kStartIndexField, &ResourceList::start_index_, &base::StringToInt); - converter->RegisterCustomField<int>( - kItemsPerPageField, &ResourceList::items_per_page_, &base::StringToInt); - converter->RegisterStringField(kTitleTField, &ResourceList::title_); - converter->RegisterRepeatedMessage(kEntryField, &ResourceList::entries_); - converter->RegisterCustomField<int64>( - kLargestChangestampField, &ResourceList::largest_changestamp_, - &base::StringToInt64); -} - -bool ResourceList::Parse(const base::Value& value) { - base::JSONValueConverter<ResourceList> converter; - if (!converter.Convert(value, this)) { - DVLOG(1) << "Invalid resource list!"; - return false; - } - - ScopedVector<ResourceEntry>::iterator iter = entries_.begin(); - while (iter != entries_.end()) { - ResourceEntry* entry = (*iter); - entry->FillRemainingFields(); - ++iter; - } - return true; -} - -// static -scoped_ptr<ResourceList> ResourceList::ExtractAndParse( - const base::Value& value) { - const base::DictionaryValue* as_dict = NULL; - const base::DictionaryValue* feed_dict = NULL; - if (value.GetAsDictionary(&as_dict) && - as_dict->GetDictionary(kFeedField, &feed_dict)) { - return ResourceList::CreateFrom(*feed_dict); - } - return scoped_ptr<ResourceList>(); -} - -// static -scoped_ptr<ResourceList> ResourceList::CreateFrom(const base::Value& value) { - scoped_ptr<ResourceList> feed(new ResourceList()); - if (!feed->Parse(value)) { - DVLOG(1) << "Invalid resource list!"; - return scoped_ptr<ResourceList>(); - } - - return feed.Pass(); -} - -bool ResourceList::GetNextFeedURL(GURL* url) const { - DCHECK(url); - for (size_t i = 0; i < links_.size(); ++i) { - if (links_[i]->type() == Link::LINK_NEXT) { - *url = links_[i]->href(); - return true; - } - } - return false; -} - -void ResourceList::ReleaseEntries(std::vector<ResourceEntry*>* entries) { - entries_.release(entries); -} - } // namespace google_apis
diff --git a/google_apis/drive/gdata_wapi_parser.h b/google_apis/drive/gdata_wapi_parser.h index 5d2ec50..2ba79b6 100644 --- a/google_apis/drive/gdata_wapi_parser.h +++ b/google_apis/drive/gdata_wapi_parser.h
@@ -6,310 +6,16 @@ #define GOOGLE_APIS_DRIVE_GDATA_WAPI_PARSER_H_ #include <string> -#include <utility> -#include <vector> -#include "base/compiler_specific.h" -#include "base/memory/scoped_ptr.h" -#include "base/memory/scoped_vector.h" -#include "base/strings/string_piece.h" -#include "base/time/time.h" -#include "url/gurl.h" - -namespace base { -class FilePath; -class DictionaryValue; -class Value; - -template <class StructType> -class JSONValueConverter; - -namespace internal { -template <class NestedType> -class RepeatedMessageConverter; -} // namespace internal - -} // namespace base +#include "base/macros.h" // Defines data elements of Google Documents API as described in // http://code.google.com/apis/documents/. namespace google_apis { -// Defines link (URL) of an entity (document, file, feed...). Each entity could -// have more than one link representing it. -class Link { - public: - enum LinkType { - LINK_UNKNOWN, - LINK_SELF, - LINK_NEXT, - LINK_PARENT, - LINK_ALTERNATE, - LINK_EDIT, - LINK_EDIT_MEDIA, - LINK_ALT_EDIT_MEDIA, - LINK_ALT_POST, - LINK_FEED, - LINK_POST, - LINK_BATCH, - LINK_RESUMABLE_EDIT_MEDIA, - LINK_RESUMABLE_CREATE_MEDIA, - LINK_TABLES_FEED, - LINK_WORKSHEET_FEED, - LINK_THUMBNAIL, - LINK_EMBED, - LINK_PRODUCT, - LINK_ICON, - LINK_OPEN_WITH, - LINK_SHARE, - }; - Link(); - ~Link(); - - // Registers the mapping between JSON field names and the members in - // this class. - static void RegisterJSONConverter(base::JSONValueConverter<Link>* converter); - - // Type of the link. - LinkType type() const { return type_; } - - // URL of the link. - const GURL& href() const { return href_; } - - // Title of the link. - const std::string& title() const { return title_; } - - // For OPEN_WITH links, this contains the application ID. For all other link - // types, it is the empty string. - const std::string& app_id() const { return app_id_; } - - // Link MIME type. - const std::string& mime_type() const { return mime_type_; } - - void set_type(LinkType type) { type_ = type; } - void set_href(const GURL& href) { href_ = href; } - void set_title(const std::string& title) { title_ = title; } - void set_app_id(const std::string& app_id) { app_id_ = app_id; } - void set_mime_type(const std::string& mime_type) { mime_type_ = mime_type; } - - private: - friend class ResourceEntry; - // Converts value of link.rel into LinkType. Outputs to |type| and returns - // true when |rel| has a valid value. Otherwise does nothing and returns - // false. - static bool GetLinkType(const base::StringPiece& rel, LinkType* type); - - // Converts value of link.rel to application ID, if there is one embedded in - // the link.rel field. Outputs to |app_id| and returns true when |rel| has a - // valid value. Otherwise does nothing and returns false. - static bool GetAppID(const base::StringPiece& rel, std::string* app_id); - - LinkType type_; - GURL href_; - std::string title_; - std::string app_id_; - std::string mime_type_; - - DISALLOW_COPY_AND_ASSIGN(Link); -}; - -// Feed links define links (URLs) to special list of entries (i.e. list of -// previous document revisions). -class ResourceLink { - public: - enum ResourceLinkType { - FEED_LINK_UNKNOWN, - FEED_LINK_ACL, - FEED_LINK_REVISIONS, - }; - ResourceLink(); - - // Registers the mapping between JSON field names and the members in - // this class. - static void RegisterJSONConverter( - base::JSONValueConverter<ResourceLink>* converter); - - // MIME type of the feed. - ResourceLinkType type() const { return type_; } - - // URL of the feed. - const GURL& href() const { return href_; } - - void set_type(ResourceLinkType type) { type_ = type; } - void set_href(const GURL& href) { href_ = href; } - - private: - friend class ResourceEntry; - // Converts value of gd$feedLink.rel into ResourceLinkType enum. - // Outputs to |result| and returns true when |rel| has a valid - // value. Otherwise does nothing and returns false. - static bool GetFeedLinkType( - const base::StringPiece& rel, ResourceLinkType* result); - - ResourceLinkType type_; - GURL href_; - - DISALLOW_COPY_AND_ASSIGN(ResourceLink); -}; - -// Author represents an author of an entity. -class Author { - public: - Author(); - - // Registers the mapping between JSON field names and the members in - // this class. - static void RegisterJSONConverter( - base::JSONValueConverter<Author>* converter); - - // Getters. - const std::string& name() const { return name_; } - const std::string& email() const { return email_; } - - void set_name(const std::string& name) { name_ = name; } - void set_email(const std::string& email) { email_ = email; } - - private: - friend class ResourceEntry; - - std::string name_; - std::string email_; - - DISALLOW_COPY_AND_ASSIGN(Author); -}; - -// Entry category. -class Category { - public: - enum CategoryType { - CATEGORY_UNKNOWN, - CATEGORY_ITEM, - CATEGORY_KIND, - CATEGORY_LABEL, - }; - - Category(); - - // Registers the mapping between JSON field names and the members in - // this class. - static void RegisterJSONConverter( - base::JSONValueConverter<Category>* converter); - - // Category label. - const std::string& label() const { return label_; } - - // Category type. - CategoryType type() const { return type_; } - - // Category term. - const std::string& term() const { return term_; } - - void set_label(const std::string& label) { label_ = label; } - void set_type(CategoryType type) { type_ = type; } - void set_term(const std::string& term) { term_ = term; } - - private: - friend class ResourceEntry; - // Converts category scheme into CategoryType enum. For example, - // http://schemas.google.com/g/2005#kind => Category::CATEGORY_KIND - // Returns false and does not change |result| when |scheme| has an - // unrecognizable value. - static bool GetCategoryTypeFromScheme( - const base::StringPiece& scheme, CategoryType* result); - - std::string label_; - CategoryType type_; - std::string term_; - - DISALLOW_COPY_AND_ASSIGN(Category); -}; - -// Content details of a resource: mime-type, url, and so on. -class Content { - public: - Content(); - - // Registers the mapping between JSON field names and the members in - // this class. - static void RegisterJSONConverter( - base::JSONValueConverter<Content>* converter); - - // The URL to download the file content. - // Note that the url can expire, so we'll fetch the latest resource - // entry before starting a download to get the download URL. - const GURL& url() const { return url_; } - const std::string& mime_type() const { return mime_type_; } - - void set_url(const GURL& url) { url_ = url; } - void set_mime_type(const std::string& mime_type) { mime_type_ = mime_type; } - - private: - friend class ResourceEntry; - - GURL url_; - std::string mime_type_; -}; - -// Base class for feed entries. This class defines fields commonly used by -// various feeds. -class CommonMetadata { - public: - CommonMetadata(); - virtual ~CommonMetadata(); - - // Returns a link of a given |type| for this entry. If not found, it returns - // NULL. - const Link* GetLinkByType(Link::LinkType type) const; - - // Entry update time. - base::Time updated_time() const { return updated_time_; } - - // Entry ETag. - const std::string& etag() const { return etag_; } - - // List of entry authors. - const ScopedVector<Author>& authors() const { return authors_; } - - // List of entry links. - const ScopedVector<Link>& links() const { return links_; } - ScopedVector<Link>* mutable_links() { return &links_; } - - // List of entry categories. - const ScopedVector<Category>& categories() const { return categories_; } - - void set_etag(const std::string& etag) { etag_ = etag; } - void set_authors(ScopedVector<Author> authors) { - authors_ = authors.Pass(); - } - void set_links(ScopedVector<Link> links) { - links_ = links.Pass(); - } - void set_categories(ScopedVector<Category> categories) { - categories_ = categories.Pass(); - } - void set_updated_time(const base::Time& updated_time) { - updated_time_ = updated_time; - } - - protected: - // Registers the mapping between JSON field names and the members in - // this class. - template<typename CommonMetadataDescendant> - static void RegisterJSONConverter( - base::JSONValueConverter<CommonMetadataDescendant>* converter); - - std::string etag_; - ScopedVector<Author> authors_; - ScopedVector<Link> links_; - ScopedVector<Category> categories_; - base::Time updated_time_; - - DISALLOW_COPY_AND_ASSIGN(CommonMetadata); -}; - // This class represents a resource entry. A resource is a generic term which // refers to a file and a directory. -class ResourceEntry : public CommonMetadata { +class ResourceEntry { public: enum ResourceEntryKind { ENTRY_KIND_UNKNOWN, @@ -317,110 +23,17 @@ ENTRY_KIND_FILE }; ResourceEntry(); - ~ResourceEntry() override; - - // Extracts "entry" dictionary from the JSON value, and parse the contents, - // using CreateFrom(). Returns NULL on failure. The input JSON data, coming - // from the gdata server, looks like: - // - // { - // "encoding": "UTF-8", - // "entry": { ... }, // This function will extract this and parse. - // "version": "1.0" - // } - // - // The caller should delete the returned object. - static scoped_ptr<ResourceEntry> ExtractAndParse(const base::Value& value); - - // Creates resource entry from parsed JSON Value. You should call - // this instead of instantiating JSONValueConverter by yourself - // because this method does some post-process for some fields. See - // FillRemainingFields comment and implementation for the details. - static scoped_ptr<ResourceEntry> CreateFrom(const base::Value& value); - - // Returns name of entry node. - static std::string GetEntryNodeName(); - - // Registers the mapping between JSON field names and the members in - // this class. - static void RegisterJSONConverter( - base::JSONValueConverter<ResourceEntry>* converter); - - // Sets true to |result| if the field exists. - // Always returns true even when the field does not exist. - static bool HasFieldPresent(const base::Value* value, bool* result); - - // Parses |value| as int64 and sets it to |result|. If the field does not - // exist, sets 0 to |result| as default value. - // Returns true if |value| is NULL or it is parsed as int64 successfully. - static bool ParseChangestamp(const base::Value* value, int64* result); + ~ResourceEntry(); // The resource ID is used to identify a resource, which looks like: // file:d41d8cd98f00b204e9800998ecf8 const std::string& resource_id() const { return resource_id_; } - // This is a URL looks like: - // https://docs.google.com/feeds/id/file%3Ad41d8cd98f00b204e9800998ecf8. - // The URL is currently not used. - const std::string& id() const { return id_; } - ResourceEntryKind kind() const { return kind_; } const std::string& title() const { return title_; } - base::Time published_time() const { return published_time_; } - base::Time last_viewed_time() const { return last_viewed_time_; } - const std::vector<std::string>& labels() const { return labels_; } - - // The URL to download a file content. - // Search for 'download_url' in gdata_wapi_requests.h for details. - const GURL& download_url() const { return content_.url(); } - - const std::string& content_mime_type() const { return content_.mime_type(); } - - // The resource links contain extra links for revisions and access control, - // etc. Note that links() contain more basic links like edit URL, - // alternative URL, etc. - const ScopedVector<ResourceLink>& resource_links() const { - return resource_links_; - } - - // File name (exists only for kinds FILE and PDF). - const std::string& filename() const { return filename_; } - - // Suggested file name (exists only for kinds FILE and PDF). - const std::string& suggested_filename() const { return suggested_filename_; } - - // File content MD5 (exists only for kinds FILE and PDF). - const std::string& file_md5() const { return file_md5_; } - - // File size (exists only for kinds FILE and PDF). - int64 file_size() const { return file_size_; } // True if the file or directory is deleted (applicable to change list only). - bool deleted() const { return deleted_ || removed_; } - - // Changestamp (exists only for change query results). - // If not exists, defaults to 0. - int64 changestamp() const { return changestamp_; } - - // Image width (exists only for images). - // If doesn't exist, then equals -1. - int64 image_width() const { return image_width_; } - - // Image height (exists only for images). - // If doesn't exist, then equals -1. - int64 image_height() const { return image_height_; } - - // Image rotation in clockwise degrees (exists only for images). - // If doesn't exist, then equals -1. - int64 image_rotation() const { return image_rotation_; } - - // The time of this modification. - // Note: This property is filled only when converted from ChangeResource. - const base::Time& modification_date() const { return modification_date_; } - - // Text version of resource entry kind. Returns an empty string for - // unknown entry kind. - std::string GetEntryKindText() const; + bool deleted() const { return deleted_; } // True if resource entry is a folder (collection). bool is_folder() const { @@ -434,169 +47,19 @@ void set_resource_id(const std::string& resource_id) { resource_id_ = resource_id; } - void set_id(const std::string& id) { id_ = id; } void set_kind(ResourceEntryKind kind) { kind_ = kind; } void set_title(const std::string& title) { title_ = title; } - void set_published_time(const base::Time& published_time) { - published_time_ = published_time; - } - void set_last_viewed_time(const base::Time& last_viewed_time) { - last_viewed_time_ = last_viewed_time; - } - void set_labels(const std::vector<std::string>& labels) { - labels_ = labels; - } - void set_content(const Content& content) { - content_ = content; - } - void set_resource_links(ScopedVector<ResourceLink> resource_links) { - resource_links_ = resource_links.Pass(); - } - void set_filename(const std::string& filename) { filename_ = filename; } - void set_suggested_filename(const std::string& suggested_filename) { - suggested_filename_ = suggested_filename; - } - void set_file_md5(const std::string& file_md5) { file_md5_ = file_md5; } - void set_file_size(int64 file_size) { file_size_ = file_size; } void set_deleted(bool deleted) { deleted_ = deleted; } - void set_removed(bool removed) { removed_ = removed; } - void set_changestamp(int64 changestamp) { changestamp_ = changestamp; } - void set_image_width(int64 image_width) { image_width_ = image_width; } - void set_image_height(int64 image_height) { image_height_ = image_height; } - void set_image_rotation(int64 image_rotation) { - image_rotation_ = image_rotation; - } - void set_modification_date(const base::Time& modification_date) { - modification_date_ = modification_date; - } - - // Fills the remaining fields where JSONValueConverter cannot catch. - // Currently, sets |kind_| and |labels_| based on the |categories_| in the - // class. - void FillRemainingFields(); private: - friend class base::internal::RepeatedMessageConverter<ResourceEntry>; - friend class ResourceList; - friend class ResumeUploadRequest; - - // Converts categories.term into ResourceEntryKind enum. - static ResourceEntryKind GetEntryKindFromTerm(const std::string& term); - std::string resource_id_; - std::string id_; ResourceEntryKind kind_; std::string title_; - base::Time published_time_; - // Last viewed value may be unreliable. See: crbug.com/152628. - base::Time last_viewed_time_; - std::vector<std::string> labels_; - Content content_; - ScopedVector<ResourceLink> resource_links_; - // Optional fields for files only. - std::string filename_; - std::string suggested_filename_; - std::string file_md5_; - int64 file_size_; bool deleted_; - bool removed_; - int64 changestamp_; - int64 image_width_; - int64 image_height_; - int64 image_rotation_; - - base::Time modification_date_; DISALLOW_COPY_AND_ASSIGN(ResourceEntry); }; -// This class represents a list of resource entries with some extra metadata -// such as the root upload URL. The feed is paginated and the rest of the -// feed can be fetched by retrieving the remaining parts of the feed from -// URLs provided by GetNextFeedURL() method. -class ResourceList : public CommonMetadata { - public: - ResourceList(); - ~ResourceList() override; - - // Extracts "feed" dictionary from the JSON value, and parse the contents, - // using CreateFrom(). Returns NULL on failure. The input JSON data, coming - // from the gdata server, looks like: - // - // { - // "encoding": "UTF-8", - // "feed": { ... }, // This function will extract this and parse. - // "version": "1.0" - // } - static scoped_ptr<ResourceList> ExtractAndParse(const base::Value& value); - - // Creates feed from parsed JSON Value. You should call this - // instead of instantiating JSONValueConverter by yourself because - // this method does some post-process for some fields. See - // FillRemainingFields comment and implementation in ResourceEntry - // class for the details. - static scoped_ptr<ResourceList> CreateFrom(const base::Value& value); - - // Registers the mapping between JSON field names and the members in - // this class. - static void RegisterJSONConverter( - base::JSONValueConverter<ResourceList>* converter); - - // Returns true and passes|url| of the next feed if the current entry list - // does not completed this feed. - bool GetNextFeedURL(GURL* url) const; - - // List of resource entries. - const ScopedVector<ResourceEntry>& entries() const { return entries_; } - ScopedVector<ResourceEntry>* mutable_entries() { return &entries_; } - - // Releases entries_ into |entries|. This is a transfer of ownership, so the - // caller is responsible for deleting the elements of |entries|. - void ReleaseEntries(std::vector<ResourceEntry*>* entries); - - // Start index of the resource entry list. - int start_index() const { return start_index_; } - - // Number of items per feed of the resource entry list. - int items_per_page() const { return items_per_page_; } - - // The largest changestamp. Next time the resource list should be fetched - // from this changestamp. - int64 largest_changestamp() const { return largest_changestamp_; } - - // Resource entry list title. - const std::string& title() { return title_; } - - void set_entries(ScopedVector<ResourceEntry> entries) { - entries_ = entries.Pass(); - } - void set_start_index(int start_index) { - start_index_ = start_index; - } - void set_items_per_page(int items_per_page) { - items_per_page_ = items_per_page; - } - void set_title(const std::string& title) { - title_ = title; - } - void set_largest_changestamp(int64 largest_changestamp) { - largest_changestamp_ = largest_changestamp; - } - - private: - // Parses and initializes data members from content of |value|. - // Return false if parsing fails. - bool Parse(const base::Value& value); - - ScopedVector<ResourceEntry> entries_; - int start_index_; - int items_per_page_; - std::string title_; - int64 largest_changestamp_; - - DISALLOW_COPY_AND_ASSIGN(ResourceList); -}; - } // namespace google_apis #endif // GOOGLE_APIS_DRIVE_GDATA_WAPI_PARSER_H_
diff --git a/google_apis/drive/gdata_wapi_parser_unittest.cc b/google_apis/drive/gdata_wapi_parser_unittest.cc deleted file mode 100644 index fd15a95c..0000000 --- a/google_apis/drive/gdata_wapi_parser_unittest.cc +++ /dev/null
@@ -1,234 +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 "google_apis/drive/gdata_wapi_parser.h" - -#include <string> - -#include "base/json/json_file_value_serializer.h" -#include "base/time/time.h" -#include "base/values.h" -#include "google_apis/drive/test_util.h" -#include "google_apis/drive/time_util.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace google_apis { - -// Test document feed parsing. -TEST(GDataWAPIParserTest, ResourceListJsonParser) { - std::string error; - scoped_ptr<base::Value> document = - test_util::LoadJSONFile("gdata/basic_feed.json"); - ASSERT_TRUE(document.get()); - ASSERT_EQ(base::Value::TYPE_DICTIONARY, document->GetType()); - scoped_ptr<ResourceList> feed(ResourceList::ExtractAndParse(*document)); - ASSERT_TRUE(feed.get()); - - base::Time update_time; - ASSERT_TRUE(util::GetTimeFromString("2011-12-14T01:03:21.151Z", - &update_time)); - - EXPECT_EQ(1, feed->start_index()); - EXPECT_EQ(1000, feed->items_per_page()); - EXPECT_EQ(update_time, feed->updated_time()); - - // Check authors. - ASSERT_EQ(1U, feed->authors().size()); - EXPECT_EQ("tester", feed->authors()[0]->name()); - EXPECT_EQ("tester@testing.com", feed->authors()[0]->email()); - - // Check links. - ASSERT_EQ(6U, feed->links().size()); - const Link* self_link = feed->GetLinkByType(Link::LINK_SELF); - ASSERT_TRUE(self_link); - EXPECT_EQ("https://self_link/", self_link->href().spec()); - EXPECT_EQ("application/atom+xml", self_link->mime_type()); - - const Link* resumable_link = - feed->GetLinkByType(Link::LINK_RESUMABLE_CREATE_MEDIA); - ASSERT_TRUE(resumable_link); - EXPECT_EQ("https://resumable_create_media_link/", - resumable_link->href().spec()); - EXPECT_EQ("application/atom+xml", resumable_link->mime_type()); - - // Check entries. - ASSERT_EQ(4U, feed->entries().size()); - - // Check a folder entry. - const ResourceEntry* folder_entry = feed->entries()[0]; - ASSERT_TRUE(folder_entry); - EXPECT_EQ(ResourceEntry::ENTRY_KIND_FOLDER, folder_entry->kind()); - EXPECT_EQ("\"HhMOFgcNHSt7ImBr\"", folder_entry->etag()); - EXPECT_EQ("folder:sub_sub_directory_folder_id", folder_entry->resource_id()); - EXPECT_EQ("https://1_folder_id", folder_entry->id()); - EXPECT_EQ("Entry 1 Title", folder_entry->title()); - base::Time entry1_update_time; - base::Time entry1_publish_time; - ASSERT_TRUE(util::GetTimeFromString("2011-04-01T18:34:08.234Z", - &entry1_update_time)); - ASSERT_TRUE(util::GetTimeFromString("2010-11-07T05:03:54.719Z", - &entry1_publish_time)); - EXPECT_EQ(entry1_update_time, folder_entry->updated_time()); - EXPECT_EQ(entry1_publish_time, folder_entry->published_time()); - - ASSERT_EQ(1U, folder_entry->authors().size()); - EXPECT_EQ("entry_tester", folder_entry->authors()[0]->name()); - EXPECT_EQ("entry_tester@testing.com", folder_entry->authors()[0]->email()); - EXPECT_EQ("https://1_folder_content_url/", - folder_entry->download_url().spec()); - EXPECT_EQ("application/atom+xml;type=feed", - folder_entry->content_mime_type()); - - ASSERT_EQ(1U, folder_entry->resource_links().size()); - const ResourceLink* feed_link = folder_entry->resource_links()[0]; - ASSERT_TRUE(feed_link); - ASSERT_EQ(ResourceLink::FEED_LINK_ACL, feed_link->type()); - - const Link* entry1_alternate_link = - folder_entry->GetLinkByType(Link::LINK_ALTERNATE); - ASSERT_TRUE(entry1_alternate_link); - EXPECT_EQ("https://1_folder_alternate_link/", - entry1_alternate_link->href().spec()); - EXPECT_EQ("text/html", entry1_alternate_link->mime_type()); - - const Link* entry1_edit_link = folder_entry->GetLinkByType(Link::LINK_EDIT); - ASSERT_TRUE(entry1_edit_link); - EXPECT_EQ("https://1_edit_link/", entry1_edit_link->href().spec()); - EXPECT_EQ("application/atom+xml", entry1_edit_link->mime_type()); - - // Check a file entry. - const ResourceEntry* file_entry = feed->entries()[1]; - ASSERT_TRUE(file_entry); - EXPECT_EQ(ResourceEntry::ENTRY_KIND_FILE, file_entry->kind()); - EXPECT_EQ("filename.m4a", file_entry->filename()); - EXPECT_EQ("sugg_file_name.m4a", file_entry->suggested_filename()); - EXPECT_EQ("3b4382ebefec6e743578c76bbd0575ce", file_entry->file_md5()); - EXPECT_EQ(892721, file_entry->file_size()); - const Link* file_parent_link = file_entry->GetLinkByType(Link::LINK_PARENT); - ASSERT_TRUE(file_parent_link); - EXPECT_EQ("https://file_link_parent/", file_parent_link->href().spec()); - EXPECT_EQ("application/atom+xml", file_parent_link->mime_type()); - EXPECT_EQ("Medical", file_parent_link->title()); - const Link* file_open_with_link = - file_entry->GetLinkByType(Link::LINK_OPEN_WITH); - ASSERT_TRUE(file_open_with_link); - EXPECT_EQ("https://xml_file_entry_open_with_link/", - file_open_with_link->href().spec()); - EXPECT_EQ("application/atom+xml", file_open_with_link->mime_type()); - EXPECT_EQ("the_app_id", file_open_with_link->app_id()); - EXPECT_EQ(654321, file_entry->changestamp()); - - const Link* file_unknown_link = file_entry->GetLinkByType(Link::LINK_UNKNOWN); - ASSERT_TRUE(file_unknown_link); - EXPECT_EQ("https://xml_file_fake_entry_open_with_link/", - file_unknown_link->href().spec()); - EXPECT_EQ("application/atom+xml", file_unknown_link->mime_type()); - EXPECT_EQ("", file_unknown_link->app_id()); - - // Check a file entry. - const ResourceEntry* resource_entry = feed->entries()[2]; - ASSERT_TRUE(resource_entry); - // Hosted documents are treated as unknown kind so that sync file system - // doesn't assume them as neither folders nor normal files. - EXPECT_EQ(ResourceEntry::ENTRY_KIND_UNKNOWN, resource_entry->kind()); - - // Check an external document entry. - const ResourceEntry* app_entry = feed->entries()[3]; - ASSERT_TRUE(app_entry); - // Hosted documents are treated as unknown kind so that sync file system - // doesn't assume them as neither folders nor normal files. - EXPECT_EQ(ResourceEntry::ENTRY_KIND_UNKNOWN, app_entry->kind()); -} - - -// Test document feed parsing. -TEST(GDataWAPIParserTest, ResourceEntryJsonParser) { - std::string error; - scoped_ptr<base::Value> document = - test_util::LoadJSONFile("gdata/file_entry.json"); - ASSERT_TRUE(document.get()); - ASSERT_EQ(base::Value::TYPE_DICTIONARY, document->GetType()); - scoped_ptr<ResourceEntry> entry(ResourceEntry::ExtractAndParse(*document)); - ASSERT_TRUE(entry.get()); - - EXPECT_EQ(ResourceEntry::ENTRY_KIND_FILE, entry->kind()); - EXPECT_EQ("\"HhMOFgxXHit7ImBr\"", entry->etag()); - EXPECT_EQ("file:2_file_resource_id", entry->resource_id()); - EXPECT_EQ("2_file_id", entry->id()); - EXPECT_EQ("File 1.mp3", entry->title()); - base::Time entry1_update_time; - base::Time entry1_publish_time; - ASSERT_TRUE(util::GetTimeFromString("2011-12-14T00:40:47.330Z", - &entry1_update_time)); - ASSERT_TRUE(util::GetTimeFromString("2011-12-13T00:40:47.330Z", - &entry1_publish_time)); - EXPECT_EQ(entry1_update_time, entry->updated_time()); - EXPECT_EQ(entry1_publish_time, entry->published_time()); - - EXPECT_EQ(1U, entry->authors().size()); - EXPECT_EQ("tester", entry->authors()[0]->name()); - EXPECT_EQ("tester@testing.com", entry->authors()[0]->email()); - EXPECT_EQ("https://file_content_url/", - entry->download_url().spec()); - EXPECT_EQ("audio/mpeg", - entry->content_mime_type()); - - // Check feed links. - ASSERT_EQ(1U, entry->resource_links().size()); - const ResourceLink* feed_link_1 = entry->resource_links()[0]; - ASSERT_TRUE(feed_link_1); - EXPECT_EQ(ResourceLink::FEED_LINK_REVISIONS, feed_link_1->type()); - - // Check links. - ASSERT_EQ(8U, entry->links().size()); - const Link* entry1_alternate_link = - entry->GetLinkByType(Link::LINK_ALTERNATE); - ASSERT_TRUE(entry1_alternate_link); - EXPECT_EQ("https://file_link_alternate/", - entry1_alternate_link->href().spec()); - EXPECT_EQ("text/html", entry1_alternate_link->mime_type()); - - const Link* entry1_edit_link = entry->GetLinkByType(Link::LINK_EDIT_MEDIA); - ASSERT_TRUE(entry1_edit_link); - EXPECT_EQ("https://file_edit_media/", - entry1_edit_link->href().spec()); - EXPECT_EQ("audio/mpeg", entry1_edit_link->mime_type()); - - const Link* entry1_self_link = entry->GetLinkByType(Link::LINK_SELF); - ASSERT_TRUE(entry1_self_link); - EXPECT_EQ("https://file1_link_self/file%3A2_file_resource_id", - entry1_self_link->href().spec()); - EXPECT_EQ("application/atom+xml", entry1_self_link->mime_type()); - EXPECT_EQ("", entry1_self_link->app_id()); - - const Link* entry1_open_with_link = - entry->GetLinkByType(Link::LINK_OPEN_WITH); - ASSERT_TRUE(entry1_open_with_link); - EXPECT_EQ("https://entry1_open_with_link/", - entry1_open_with_link->href().spec()); - EXPECT_EQ("application/atom+xml", entry1_open_with_link->mime_type()); - EXPECT_EQ("the_app_id", entry1_open_with_link->app_id()); - - const Link* entry1_unknown_link = entry->GetLinkByType(Link::LINK_UNKNOWN); - ASSERT_TRUE(entry1_unknown_link); - EXPECT_EQ("https://entry1_fake_entry_open_with_link/", - entry1_unknown_link->href().spec()); - EXPECT_EQ("application/atom+xml", entry1_unknown_link->mime_type()); - EXPECT_EQ("", entry1_unknown_link->app_id()); - - // Check a file properties. - EXPECT_EQ(ResourceEntry::ENTRY_KIND_FILE, entry->kind()); - EXPECT_EQ("File 1.mp3", entry->filename()); - EXPECT_EQ("File 1.mp3", entry->suggested_filename()); - EXPECT_EQ("3b4382ebefec6e743578c76bbd0575ce", entry->file_md5()); - EXPECT_EQ(892721, entry->file_size()); - - // WAPI doesn't provide image metadata, but these fields are available - // since this class can wrap data received from Drive API (via a converter). - EXPECT_EQ(-1, entry->image_width()); - EXPECT_EQ(-1, entry->image_height()); - EXPECT_EQ(-1, entry->image_rotation()); -} - -} // namespace google_apis
diff --git a/google_apis/drive/gdata_wapi_requests.cc b/google_apis/drive/gdata_wapi_requests.cc deleted file mode 100644 index 7c3e532..0000000 --- a/google_apis/drive/gdata_wapi_requests.cc +++ /dev/null
@@ -1,81 +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 "google_apis/drive/gdata_wapi_requests.h" - -#include "base/location.h" -#include "base/sequenced_task_runner.h" -#include "base/task_runner_util.h" -#include "base/values.h" -#include "google_apis/drive/gdata_wapi_parser.h" -#include "google_apis/drive/gdata_wapi_url_generator.h" - -namespace google_apis { - -namespace { - -scoped_ptr<ResourceEntry> ParseResourceEntry(const std::string& json) { - scoped_ptr<base::Value> value = ParseJson(json); - return value ? ResourceEntry::ExtractAndParse(*value) : - scoped_ptr<ResourceEntry>(); -} - -} // namespace - -GetResourceEntryRequest::GetResourceEntryRequest( - RequestSender* sender, - const GDataWapiUrlGenerator& url_generator, - const std::string& resource_id, - const GURL& embed_origin, - const GetResourceEntryCallback& callback) - : UrlFetchRequestBase(sender), - url_generator_(url_generator), - resource_id_(resource_id), - embed_origin_(embed_origin), - callback_(callback), - weak_ptr_factory_(this) { - DCHECK(!callback.is_null()); -} - -GetResourceEntryRequest::~GetResourceEntryRequest() {} - -GURL GetResourceEntryRequest::GetURL() const { - return url_generator_.GenerateEditUrlWithEmbedOrigin( - resource_id_, embed_origin_); -} - -void GetResourceEntryRequest::ProcessURLFetchResults( - const net::URLFetcher* source) { - GDataErrorCode error = GetErrorCode(); - switch (error) { - case HTTP_SUCCESS: - case HTTP_CREATED: - base::PostTaskAndReplyWithResult( - blocking_task_runner(), - FROM_HERE, - base::Bind(&ParseResourceEntry, response_writer()->data()), - base::Bind(&GetResourceEntryRequest::OnDataParsed, - weak_ptr_factory_.GetWeakPtr(), error)); - break; - default: - RunCallbackOnPrematureFailure(error); - OnProcessURLFetchResultsComplete(); - break; - } -} - -void GetResourceEntryRequest::RunCallbackOnPrematureFailure( - GDataErrorCode error) { - callback_.Run(error, scoped_ptr<ResourceEntry>()); -} - -void GetResourceEntryRequest::OnDataParsed(GDataErrorCode error, - scoped_ptr<ResourceEntry> entry) { - if (!entry) - error = GDATA_PARSE_ERROR; - callback_.Run(error, entry.Pass()); - OnProcessURLFetchResultsComplete(); -} - -} // namespace google_apis
diff --git a/google_apis/drive/gdata_wapi_requests.h b/google_apis/drive/gdata_wapi_requests.h deleted file mode 100644 index 4a9962ba..0000000 --- a/google_apis/drive/gdata_wapi_requests.h +++ /dev/null
@@ -1,59 +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 GOOGLE_APIS_DRIVE_GDATA_WAPI_REQUESTS_H_ -#define GOOGLE_APIS_DRIVE_GDATA_WAPI_REQUESTS_H_ - -#include <string> - -#include "google_apis/drive/base_requests.h" -#include "google_apis/drive/gdata_wapi_url_generator.h" - -namespace google_apis { - -class ResourceEntry; - -// Callback type for GetResourceEntryRequest. -typedef base::Callback<void(GDataErrorCode error, - scoped_ptr<ResourceEntry> entry)> - GetResourceEntryCallback; - -// This class performs the request for fetching a single resource entry. -class GetResourceEntryRequest : public UrlFetchRequestBase { - public: - // |callback| must not be null. - GetResourceEntryRequest(RequestSender* sender, - const GDataWapiUrlGenerator& url_generator, - const std::string& resource_id, - const GURL& embed_origin, - const GetResourceEntryCallback& callback); - ~GetResourceEntryRequest() override; - - protected: - // UrlFetchRequestBase overrides. - void ProcessURLFetchResults(const net::URLFetcher* source) override; - void RunCallbackOnPrematureFailure(GDataErrorCode error) override; - GURL GetURL() const override; - - private: - void OnDataParsed(GDataErrorCode error, scoped_ptr<ResourceEntry> entry); - - const GDataWapiUrlGenerator url_generator_; - // Resource id of the requested entry. - const std::string resource_id_; - // Embed origin for an url to the sharing dialog. Can be empty. - GURL embed_origin_; - - const GetResourceEntryCallback callback_; - - // 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<GetResourceEntryRequest> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(GetResourceEntryRequest); -}; - -} // namespace google_apis - -#endif // GOOGLE_APIS_DRIVE_GDATA_WAPI_REQUESTS_H_
diff --git a/google_apis/drive/gdata_wapi_requests_unittest.cc b/google_apis/drive/gdata_wapi_requests_unittest.cc deleted file mode 100644 index 87dc8c6..0000000 --- a/google_apis/drive/gdata_wapi_requests_unittest.cc +++ /dev/null
@@ -1,153 +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 "base/bind.h" -#include "base/message_loop/message_loop.h" -#include "base/run_loop.h" -#include "google_apis/drive/dummy_auth_service.h" -#include "google_apis/drive/gdata_wapi_parser.h" -#include "google_apis/drive/gdata_wapi_requests.h" -#include "google_apis/drive/gdata_wapi_url_generator.h" -#include "google_apis/drive/request_sender.h" -#include "google_apis/drive/test_util.h" -#include "net/base/escape.h" -#include "net/test/embedded_test_server/embedded_test_server.h" -#include "net/test/embedded_test_server/http_request.h" -#include "net/test/embedded_test_server/http_response.h" -#include "net/url_request/url_request_test_util.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace google_apis { - -namespace { - -const char kTestUserAgent[] = "test-user-agent"; - -class GDataWapiRequestsTest : public testing::Test { - public: - void SetUp() override { - request_context_getter_ = new net::TestURLRequestContextGetter( - message_loop_.message_loop_proxy()); - - request_sender_.reset(new RequestSender(new DummyAuthService, - request_context_getter_.get(), - message_loop_.message_loop_proxy(), - kTestUserAgent)); - - ASSERT_TRUE(test_server_.InitializeAndWaitUntilReady()); - test_server_.RegisterRequestHandler( - base::Bind(&GDataWapiRequestsTest::HandleResourceFeedRequest, - base::Unretained(this))); - - GURL test_base_url = test_util::GetBaseUrlForTesting(test_server_.port()); - url_generator_.reset(new GDataWapiUrlGenerator(test_base_url)); - } - - protected: - // Handles a request for fetching a resource feed. - scoped_ptr<net::test_server::HttpResponse> HandleResourceFeedRequest( - const net::test_server::HttpRequest& request) { - http_request_ = request; - - const GURL absolute_url = test_server_.GetURL(request.relative_url); - std::string remaining_path; - - if (!test_util::RemovePrefix(absolute_url.path(), - "/feeds/default/private/full", - &remaining_path)) { - return nullptr; - } - - // Process a feed for a single resource ID. - const std::string resource_id = net::UnescapeURLComponent( - remaining_path.substr(1), net::UnescapeRule::URL_SPECIAL_CHARS); - if (resource_id == "file:2_file_resource_id") { - scoped_ptr<net::test_server::BasicHttpResponse> result( - test_util::CreateHttpResponseFromFile( - test_util::GetTestFilePath("gdata/file_entry.json"))); - return result.Pass(); - } else if (resource_id == "invalid_resource_id") { - // Check if this is an authorization request for an app. - // This emulates to return invalid formatted result from the server. - if (request.method == net::test_server::METHOD_PUT && - request.content.find("<docs:authorizedApp>") != std::string::npos) { - scoped_ptr<net::test_server::BasicHttpResponse> result( - test_util::CreateHttpResponseFromFile( - test_util::GetTestFilePath("drive/testfile.txt"))); - return result.Pass(); - } - } - - return nullptr; - } - - base::MessageLoopForIO message_loop_; // Test server needs IO thread. - net::test_server::EmbeddedTestServer test_server_; - scoped_ptr<RequestSender> request_sender_; - scoped_ptr<GDataWapiUrlGenerator> url_generator_; - scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_; - - // The incoming HTTP request is saved so tests can verify the request - // parameters like HTTP method (ex. some requests should use DELETE - // instead of GET). - net::test_server::HttpRequest http_request_; -}; - -} // namespace - -TEST_F(GDataWapiRequestsTest, GetResourceEntryRequest_ValidResourceId) { - GDataErrorCode result_code = GDATA_OTHER_ERROR; - scoped_ptr<ResourceEntry> result_data; - - { - base::RunLoop run_loop; - GetResourceEntryRequest* request = new GetResourceEntryRequest( - request_sender_.get(), - *url_generator_, - "file:2_file_resource_id", // resource ID - GURL(), // embed origin - test_util::CreateQuitCallback( - &run_loop, - test_util::CreateCopyResultCallback(&result_code, &result_data))); - request_sender_->StartRequestWithRetry(request); - run_loop.Run(); - } - - EXPECT_EQ(HTTP_SUCCESS, result_code); - EXPECT_EQ(net::test_server::METHOD_GET, http_request_.method); - EXPECT_EQ("/feeds/default/private/full/file%3A2_file_resource_id" - "?v=3&alt=json&showroot=true", - http_request_.relative_url); - EXPECT_TRUE(result_data); - EXPECT_EQ("File 1.mp3", result_data->filename()); - EXPECT_EQ("3b4382ebefec6e743578c76bbd0575ce", result_data->file_md5()); -} - -TEST_F(GDataWapiRequestsTest, GetResourceEntryRequest_InvalidResourceId) { - GDataErrorCode result_code = GDATA_OTHER_ERROR; - scoped_ptr<ResourceEntry> result_data; - - { - base::RunLoop run_loop; - GetResourceEntryRequest* request = new GetResourceEntryRequest( - request_sender_.get(), - *url_generator_, - "<invalid>", // resource ID - GURL(), // embed origin - test_util::CreateQuitCallback( - &run_loop, - test_util::CreateCopyResultCallback(&result_code, &result_data))); - request_sender_->StartRequestWithRetry(request); - run_loop.Run(); - } - - EXPECT_EQ(HTTP_NOT_FOUND, result_code); - EXPECT_EQ(net::test_server::METHOD_GET, http_request_.method); - EXPECT_EQ("/feeds/default/private/full/%3Cinvalid%3E?v=3&alt=json" - "&showroot=true", - http_request_.relative_url); - ASSERT_FALSE(result_data); -} - -} // namespace google_apis
diff --git a/google_apis/drive/gdata_wapi_url_generator.cc b/google_apis/drive/gdata_wapi_url_generator.cc deleted file mode 100644 index ffdb0f3..0000000 --- a/google_apis/drive/gdata_wapi_url_generator.cc +++ /dev/null
@@ -1,69 +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 "google_apis/drive/gdata_wapi_url_generator.h" - -#include "base/logging.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/stringprintf.h" -#include "net/base/escape.h" -#include "net/base/url_util.h" -#include "url/gurl.h" - -namespace google_apis { -namespace { - -// URL requesting single resource entry whose resource id is followed by this -// prefix. -const char kGetEditURLPrefix[] = "/feeds/default/private/full/"; - -} // namespace - -const char GDataWapiUrlGenerator::kBaseUrlForProduction[] = - "https://docs.google.com/"; - -// static -GURL GDataWapiUrlGenerator::AddStandardUrlParams(const GURL& url) { - GURL result = net::AppendOrReplaceQueryParameter(url, "v", "3"); - result = net::AppendOrReplaceQueryParameter(result, "alt", "json"); - result = net::AppendOrReplaceQueryParameter(result, "showroot", "true"); - return result; -} - -GDataWapiUrlGenerator::GDataWapiUrlGenerator(const GURL& base_url) - : base_url_(base_url) { -} - -GDataWapiUrlGenerator::~GDataWapiUrlGenerator() { -} - -GURL GDataWapiUrlGenerator::GenerateEditUrl( - const std::string& resource_id) const { - return AddStandardUrlParams(GenerateEditUrlWithoutParams(resource_id)); -} - -GURL GDataWapiUrlGenerator::GenerateEditUrlWithoutParams( - const std::string& resource_id) const { - return base_url_.Resolve(kGetEditURLPrefix + net::EscapePath(resource_id)); -} - -GURL GDataWapiUrlGenerator::GenerateEditUrlWithEmbedOrigin( - const std::string& resource_id, const GURL& embed_origin) const { - GURL url = GenerateEditUrl(resource_id); - if (!embed_origin.is_empty()) { - // Construct a valid serialized embed origin from an url, according to - // WD-html5-20110525. Such string has to be built manually, since - // GURL::spec() always adds the trailing slash. Moreover, ports are - // currently not supported. - DCHECK(!embed_origin.has_port()); - DCHECK(!embed_origin.has_path() || embed_origin.path() == "/"); - const std::string serialized_embed_origin = - embed_origin.scheme() + "://" + embed_origin.host(); - url = net::AppendOrReplaceQueryParameter( - url, "embedOrigin", serialized_embed_origin); - } - return url; -} - -} // namespace google_apis
diff --git a/google_apis/drive/gdata_wapi_url_generator.h b/google_apis/drive/gdata_wapi_url_generator.h deleted file mode 100644 index c0486cf..0000000 --- a/google_apis/drive/gdata_wapi_url_generator.h +++ /dev/null
@@ -1,59 +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. -// -// URL utility functions for Google Documents List API (aka WAPI). - -#ifndef GOOGLE_APIS_DRIVE_GDATA_WAPI_URL_GENERATOR_H_ -#define GOOGLE_APIS_DRIVE_GDATA_WAPI_URL_GENERATOR_H_ - -#include <string> - -#include "url/gurl.h" - -namespace google_apis { - -// The class is used to generate URLs for communicating with the WAPI server. -// for production, and the local server for testing. -class GDataWapiUrlGenerator { - public: - GDataWapiUrlGenerator(const GURL& base_url); - ~GDataWapiUrlGenerator(); - - // The base URL for communicating with the WAPI server for production. - static const char kBaseUrlForProduction[]; - - // The base URL for the file download server for production. - static const char kBaseDownloadUrlForProduction[]; - - // Adds additional parameters for API version, output content type and to - // show folders in the feed are added to document feed URLs. - static GURL AddStandardUrlParams(const GURL& url); - - // Generates a URL for getting or editing the resource entry of - // the given resource ID. - GURL GenerateEditUrl(const std::string& resource_id) const; - - // Generates a URL for getting or editing the resource entry of the - // given resource ID without query params. - // Note that, in order to access to the WAPI server, it is necessary to - // append some query parameters to the URL. GenerateEditUrl declared above - // should be used in such cases. This method is designed for constructing - // the data, such as xml element/attributes in request body containing - // edit urls. - GURL GenerateEditUrlWithoutParams(const std::string& resource_id) const; - - // Generates a URL for getting or editing the resource entry of the given - // resource ID with additionally passed embed origin. This is used to fetch - // share urls for the sharing dialog to be embedded with the |embed_origin| - // origin. - GURL GenerateEditUrlWithEmbedOrigin(const std::string& resource_id, - const GURL& embed_origin) const; - - private: - const GURL base_url_; -}; - -} // namespace google_apis - -#endif // GOOGLE_APIS_DRIVE_GDATA_WAPI_URL_GENERATOR_H_
diff --git a/google_apis/drive/gdata_wapi_url_generator_unittest.cc b/google_apis/drive/gdata_wapi_url_generator_unittest.cc deleted file mode 100644 index 0ac8508d..0000000 --- a/google_apis/drive/gdata_wapi_url_generator_unittest.cc +++ /dev/null
@@ -1,60 +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 "google_apis/drive/gdata_wapi_url_generator.h" - -#include "testing/gtest/include/gtest/gtest.h" -#include "url/gurl.h" -#include "url/url_util.h" - -namespace google_apis { - -class GDataWapiUrlGeneratorTest : public testing::Test { - public: - GDataWapiUrlGeneratorTest() - : url_generator_( - GURL(GDataWapiUrlGenerator::kBaseUrlForProduction)) { - } - - protected: - GDataWapiUrlGenerator url_generator_; -}; - -TEST_F(GDataWapiUrlGeneratorTest, AddStandardUrlParams) { - EXPECT_EQ("http://www.example.com/?v=3&alt=json&showroot=true", - GDataWapiUrlGenerator::AddStandardUrlParams( - GURL("http://www.example.com")).spec()); -} - -TEST_F(GDataWapiUrlGeneratorTest, GenerateEditUrl) { - EXPECT_EQ( - "https://docs.google.com/feeds/default/private/full/XXX?v=3&alt=json" - "&showroot=true", - url_generator_.GenerateEditUrl("XXX").spec()); -} - -TEST_F(GDataWapiUrlGeneratorTest, GenerateEditUrlWithoutParams) { - EXPECT_EQ( - "https://docs.google.com/feeds/default/private/full/XXX", - url_generator_.GenerateEditUrlWithoutParams("XXX").spec()); -} - -TEST_F(GDataWapiUrlGeneratorTest, GenerateEditUrlWithEmbedOrigin) { - url::AddStandardScheme("chrome-extension"); - - EXPECT_EQ( - "https://docs.google.com/feeds/default/private/full/XXX?v=3&alt=json" - "&showroot=true&embedOrigin=chrome-extension%3A%2F%2Ftest", - url_generator_.GenerateEditUrlWithEmbedOrigin( - "XXX", - GURL("chrome-extension://test")).spec()); - EXPECT_EQ( - "https://docs.google.com/feeds/default/private/full/XXX?v=3&alt=json" - "&showroot=true", - url_generator_.GenerateEditUrlWithEmbedOrigin( - "XXX", - GURL()).spec()); -} - -} // namespace google_apis
diff --git a/google_apis/drive/test_util.cc b/google_apis/drive/test_util.cc index 6d92eb0..ee400c0 100644 --- a/google_apis/drive/test_util.cc +++ b/google_apis/drive/test_util.cc
@@ -17,7 +17,6 @@ #include "base/strings/stringprintf.h" #include "google_apis/drive/drive_api_parser.h" #include "google_apis/drive/gdata_wapi_parser.h" -#include "google_apis/drive/gdata_wapi_requests.h" #include "net/test/embedded_test_server/http_request.h" #include "net/test/embedded_test_server/http_response.h" #include "url/gurl.h"
diff --git a/google_apis/google_apis.gyp b/google_apis/google_apis.gyp index 228fba8..436e7b1 100644 --- a/google_apis/google_apis.gyp +++ b/google_apis/google_apis.gyp
@@ -57,12 +57,8 @@ 'drive/drive_common_callbacks.h', 'drive/gdata_errorcode.cc', 'drive/gdata_errorcode.h', - 'drive/gdata_wapi_requests.cc', - 'drive/gdata_wapi_requests.h', 'drive/gdata_wapi_parser.cc', 'drive/gdata_wapi_parser.h', - 'drive/gdata_wapi_url_generator.cc', - 'drive/gdata_wapi_url_generator.h', 'drive/request_sender.cc', 'drive/request_sender.h', 'drive/request_util.cc', @@ -161,9 +157,6 @@ 'drive/drive_api_parser_unittest.cc', 'drive/drive_api_requests_unittest.cc', 'drive/drive_api_url_generator_unittest.cc', - 'drive/gdata_wapi_parser_unittest.cc', - 'drive/gdata_wapi_requests_unittest.cc', - 'drive/gdata_wapi_url_generator_unittest.cc', 'drive/request_sender_unittest.cc', 'drive/request_util_unittest.cc', 'drive/time_util_unittest.cc',
diff --git a/gpu/GLES2/gl2chromium_autogen.h b/gpu/GLES2/gl2chromium_autogen.h index 8a0011c..1110c0af 100644 --- a/gpu/GLES2/gl2chromium_autogen.h +++ b/gpu/GLES2/gl2chromium_autogen.h
@@ -91,6 +91,7 @@ #define glGetBufferParameteriv GLES2_GET_FUN(GetBufferParameteriv) #define glGetError GLES2_GET_FUN(GetError) #define glGetFloatv GLES2_GET_FUN(GetFloatv) +#define glGetFragDataLocation GLES2_GET_FUN(GetFragDataLocation) #define glGetFramebufferAttachmentParameteriv \ GLES2_GET_FUN(GetFramebufferAttachmentParameteriv) #define glGetIntegerv GLES2_GET_FUN(GetIntegerv)
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py index 922c1f94..577861a 100755 --- a/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -1372,8 +1372,7 @@ 'type': 'GLenum', 'is_complete': True, 'valid': [ - #TODO(zmo): avoid using the direct number. - '0x9117', # GL_SYNC_GPU_COMMANDS_COMPLETE + 'GL_SYNC_GPU_COMMANDS_COMPLETE', ], 'invalid': [ '0', @@ -2029,7 +2028,16 @@ 'cmd_args': 'GLidProgram program, uint32_t name_bucket_id, GLint* location', 'result': ['GLint'], - 'error_return': -1, # http://www.opengl.org/sdk/docs/man/xhtml/glGetAttribLocation.xml + 'error_return': -1, + }, + 'GetFragDataLocation': { + 'type': 'Custom', + 'data_transfer_methods': ['shm'], + 'cmd_args': + 'GLidProgram program, uint32_t name_bucket_id, GLint* location', + 'result': ['GLint'], + 'error_return': -1, + 'unsafe': True, }, 'GetBooleanv': { 'type': 'GETn', @@ -2441,7 +2449,6 @@ 'type': 'PUTSTR', 'decoder_func': 'DoShaderSource', 'data_transfer_methods': ['bucket'], - 'client_test': False, 'cmd_args': 'GLuint shader, const char** str', 'pepper_args': @@ -3840,7 +3847,7 @@ }) else: if client_test != False: - file.Write("// TODO: Implement unit test for %s\n" % func.name) + file.Write("// TODO(zmo): Implement unit test for %s\n" % func.name) def WriteDestinationInitalizationValidation(self, func, file): """Writes the client side destintion initialization validation.""" @@ -6507,6 +6514,245 @@ file.Write("}\n") file.Write("\n") + def WriteGLES2ImplementationUnitTest(self, func, file): + """Overrriden from TypeHandler.""" + code = """ +TEST_F(GLES2ImplementationTest, %(name)s) { + const uint32 kBucketId = GLES2Implementation::kResultBucketId; + const char* kString1 = "happy"; + const char* kString2 = "ending"; + const size_t kString1Size = ::strlen(kString1) + 1; + const size_t kString2Size = ::strlen(kString2) + 1; + const size_t kHeaderSize = sizeof(GLint) * 3; + const size_t kSourceSize = kHeaderSize + kString1Size + kString2Size; + const size_t kPaddedHeaderSize = + transfer_buffer_->RoundToAlignment(kHeaderSize); + const size_t kPaddedString1Size = + transfer_buffer_->RoundToAlignment(kString1Size); + const size_t kPaddedString2Size = + transfer_buffer_->RoundToAlignment(kString2Size); + struct Cmds { + cmd::SetBucketSize set_bucket_size; + cmd::SetBucketData set_bucket_header; + cmd::SetToken set_token1; + cmd::SetBucketData set_bucket_data1; + cmd::SetToken set_token2; + cmd::SetBucketData set_bucket_data2; + cmd::SetToken set_token3; + cmds::ShaderSourceBucket shader_source_bucket; + cmd::SetBucketSize clear_bucket_size; + }; + + ExpectedMemoryInfo mem0 = GetExpectedMemory(kPaddedHeaderSize); + ExpectedMemoryInfo mem1 = GetExpectedMemory(kPaddedString1Size); + ExpectedMemoryInfo mem2 = GetExpectedMemory(kPaddedString2Size); + + Cmds expected; + expected.set_bucket_size.Init(kBucketId, kSourceSize); + expected.set_bucket_header.Init( + kBucketId, 0, kHeaderSize, mem0.id, mem0.offset); + expected.set_token1.Init(GetNextToken()); + expected.set_bucket_data1.Init( + kBucketId, kHeaderSize, kString1Size, mem1.id, mem1.offset); + expected.set_token2.Init(GetNextToken()); + expected.set_bucket_data2.Init( + kBucketId, kHeaderSize + kString1Size, kString2Size, mem2.id, + mem2.offset); + expected.set_token3.Init(GetNextToken()); + expected.shader_source_bucket.Init(%(cmd_args)s, kBucketId); + expected.clear_bucket_size.Init(kBucketId, 0); + const char* kStrings[] = { kString1, kString2 }; + gl_->%(name)s(%(gl_args)s); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); +} +""" + gl_args = [] + cmd_args = [] + for arg in func.GetOriginalArgs(): + if arg == self.__GetDataArg(func): + gl_args.append('kStrings') + elif arg == self.__GetLengthArg(func): + gl_args.append('NULL') + elif arg.name == 'count': + gl_args.append('2') + else: + gl_args.append(arg.GetValidClientSideArg(func)) + cmd_args.append(arg.GetValidClientSideArg(func)) + file.Write(code % { + 'name': func.name, + 'gl_args': ", ".join(gl_args), + 'cmd_args': ", ".join(cmd_args), + }) + + if self.__GetLengthArg(func) == None: + return + code = """ +TEST_F(GLES2ImplementationTest, %(name)sWithLength) { + const uint32 kBucketId = GLES2Implementation::kResultBucketId; + const char* kString = "foobar******"; + const size_t kStringSize = 6; // We only need "foobar". + const size_t kHeaderSize = sizeof(GLint) * 2; + const size_t kSourceSize = kHeaderSize + kStringSize + 1; + const size_t kPaddedHeaderSize = + transfer_buffer_->RoundToAlignment(kHeaderSize); + const size_t kPaddedStringSize = + transfer_buffer_->RoundToAlignment(kStringSize + 1); + struct Cmds { + cmd::SetBucketSize set_bucket_size; + cmd::SetBucketData set_bucket_header; + cmd::SetToken set_token1; + cmd::SetBucketData set_bucket_data; + cmd::SetToken set_token2; + cmds::ShaderSourceBucket shader_source_bucket; + cmd::SetBucketSize clear_bucket_size; + }; + + ExpectedMemoryInfo mem0 = GetExpectedMemory(kPaddedHeaderSize); + ExpectedMemoryInfo mem1 = GetExpectedMemory(kPaddedStringSize); + + Cmds expected; + expected.set_bucket_size.Init(kBucketId, kSourceSize); + expected.set_bucket_header.Init( + kBucketId, 0, kHeaderSize, mem0.id, mem0.offset); + expected.set_token1.Init(GetNextToken()); + expected.set_bucket_data.Init( + kBucketId, kHeaderSize, kStringSize + 1, mem1.id, mem1.offset); + expected.set_token2.Init(GetNextToken()); + expected.shader_source_bucket.Init(%(cmd_args)s, kBucketId); + expected.clear_bucket_size.Init(kBucketId, 0); + const char* kStrings[] = { kString }; + const GLint kLength[] = { kStringSize }; + gl_->%(name)s(%(gl_args)s); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); +} +""" + gl_args = [] + for arg in func.GetOriginalArgs(): + if arg == self.__GetDataArg(func): + gl_args.append('kStrings') + elif arg == self.__GetLengthArg(func): + gl_args.append('kLength') + elif arg.name == 'count': + gl_args.append('1') + else: + gl_args.append(arg.GetValidClientSideArg(func)) + file.Write(code % { + 'name': func.name, + 'gl_args': ", ".join(gl_args), + 'cmd_args': ", ".join(cmd_args), + }) + + def WriteBucketServiceUnitTest(self, func, file, *extras): + """Overrriden from TypeHandler.""" + cmd_args = [] + cmd_args_with_invalid_id = [] + for index, arg in enumerate(func.GetOriginalArgs()): + if (arg == self.__GetLengthArg(func) or + arg == self.__GetDataArg(func) or arg.name == 'count'): + continue + if index == 0: # Resource ID arg + cmd_args.append(arg.GetValidArg(func)) + cmd_args_with_invalid_id.append('kInvalidClientId') + else: + cmd_args.append(arg.GetValidArg(func)) + cmd_args_with_invalid_id.append(arg.GetValidArg(func)) + + test = """ +TEST_P(%(test_name)s, %(name)sValidArgs) { + const uint32 kBucketId = 123; + const char kSource0[] = "hello"; + const char* kSource[] = { kSource0 }; + const char kValidStrEnd = 0; + SetBucketAsCStrings(kBucketId, 1, kSource, 1, kValidStrEnd); + cmds::%(name)s cmd; + cmd.Init(%(cmd_args)s, kBucketId); + decoder_->set_unsafe_es3_apis_enabled(true); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));""" + if func.IsUnsafe(): + test += """ + decoder_->set_unsafe_es3_apis_enabled(false); + EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd)); +""" + test += """ +} +""" + self.WriteValidUnitTest(func, file, test, { + 'cmd_args': ", ".join(cmd_args), + }, *extras) + + test = """ +TEST_P(%(test_name)s, %(name)sInvalidArgs) { + const uint32 kBucketId = 123; + const char kSource0[] = "hello"; + const char* kSource[] = { kSource0 }; + const char kValidStrEnd = 0; + decoder_->set_unsafe_es3_apis_enabled(true); + cmds::%(name)s cmd; + // Test no bucket. + cmd.Init(%(cmd_args)s, kBucketId); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); + // Test invalid client. + SetBucketAsCStrings(kBucketId, 1, kSource, 1, kValidStrEnd); + cmd.Init(%(cmd_args_with_invalid_id)s, kBucketId); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); +} +""" + self.WriteValidUnitTest(func, file, test, { + 'cmd_args': ", ".join(cmd_args), + 'cmd_args_with_invalid_id': ", ".join(cmd_args_with_invalid_id), + }, *extras) + + test = """ +TEST_P(%(test_name)s, %(name)sInvalidHeader) { + const uint32 kBucketId = 123; + const char kSource0[] = "hello"; + const char* kSource[] = { kSource0 }; + const char kValidStrEnd = 0; + const GLsizei kCount = static_cast<GLsizei>(arraysize(kSource)); + const GLsizei kTests[] = { + kCount, + 0, + std::numeric_limits<GLsizei>::max(), + -1, + kCount, + }; + decoder_->set_unsafe_es3_apis_enabled(true); + for (size_t ii = 0; ii < arraysize(kTests); ++ii) { + SetBucketAsCStrings(kBucketId, 1, kSource, kTests[ii], kValidStrEnd); + cmds::%(name)s cmd; + cmd.Init(%(cmd_args)s, kBucketId); + if (kTests[ii] == kCount) { + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + } else { + EXPECT_EQ(error::kInvalidArguments, ExecuteCmd(cmd)); + } + } + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} +""" + self.WriteValidUnitTest(func, file, test, { + 'cmd_args': ", ".join(cmd_args), + }, *extras) + + test = """ +TEST_P(%(test_name)s, %(name)sInvalidStringEnding) { + const uint32 kBucketId = 123; + const char kSource0[] = "hello"; + const char* kSource[] = { kSource0 }; + const char kInvalidStrEnd = '*'; + SetBucketAsCStrings(kBucketId, 1, kSource, 1, kInvalidStrEnd); + cmds::%(name)s cmd; + cmd.Init(%(cmd_args)s, kBucketId); + decoder_->set_unsafe_es3_apis_enabled(true); + EXPECT_EQ(error::kInvalidArguments, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} +""" + self.WriteValidUnitTest(func, file, test, { + 'cmd_args': ", ".join(cmd_args), + }, *extras) + class PUTXnHandler(ArrayArgTypeHandler): """Handler for glUniform?f functions.""" @@ -7539,39 +7785,6 @@ return "static_cast<const void*>(%s)" % self.name -class BucketPointerArgument(Argument): - """A class that represents an bucket argument to a function.""" - - def __init__(self, name, type): - Argument.__init__(self, name, type) - - def AddCmdArgs(self, args): - """Overridden from Argument.""" - pass - - def WriteGetCode(self, file): - """Overridden from Argument.""" - file.Write( - " %s %s = bucket->GetData(0, data_size);\n" % - (self.type, self.name)) - - def WriteValidationCode(self, file, func): - """Overridden from Argument.""" - pass - - def GetImmediateVersion(self): - """Overridden from Argument.""" - return None - - def WriteDestinationInitalizationValidation(self, file, func): - """Overridden from Argument.""" - self.WriteDestinationInitalizationValidatationIfNeeded(file, func) - - def GetLogArg(self): - """Overridden from Argument.""" - return "static_cast<const void*>(%s)" % self.name - - class PointerArgument(Argument): """A class that represents a pointer argument to a function.""" @@ -7579,11 +7792,11 @@ Argument.__init__(self, name, type) def IsPointer(self): - """Returns true if argument is a pointer.""" + """Overridden from Argument.""" return True def IsPointer2D(self): - """Returns true if argument is a 2D pointer.""" + """Overridden from Argument.""" return self.type.count('*') == 2 def GetPointedType(self): @@ -7661,12 +7874,53 @@ self.WriteDestinationInitalizationValidatationIfNeeded(file, func) +class BucketPointerArgument(PointerArgument): + """A class that represents an bucket argument to a function.""" + + def __init__(self, name, type): + Argument.__init__(self, name, type) + + def AddCmdArgs(self, args): + """Overridden from Argument.""" + pass + + def WriteGetCode(self, file): + """Overridden from Argument.""" + file.Write( + " %s %s = bucket->GetData(0, data_size);\n" % + (self.type, self.name)) + + def WriteValidationCode(self, file, func): + """Overridden from Argument.""" + pass + + def GetImmediateVersion(self): + """Overridden from Argument.""" + return None + + def WriteDestinationInitalizationValidation(self, file, func): + """Overridden from Argument.""" + self.WriteDestinationInitalizationValidatationIfNeeded(file, func) + + def GetLogArg(self): + """Overridden from Argument.""" + return "static_cast<const void*>(%s)" % self.name + + class InputStringBucketArgument(Argument): """A string input argument where the string is passed in a bucket.""" def __init__(self, name, type): Argument.__init__(self, name + "_bucket_id", "uint32_t") + def IsPointer(self): + """Overridden from Argument.""" + return True + + def IsPointer2D(self): + """Overridden from Argument.""" + return False + class InputStringArrayBucketArgument(Argument): """A string array input argument where the strings are passed in a bucket.""" @@ -7732,6 +7986,14 @@ def GetValidGLArg(self, func): return "_" + def IsPointer(self): + """Overridden from Argument.""" + return True + + def IsPointer2D(self): + """Overridden from Argument.""" + return True + class ResourceIdArgument(Argument): """A class that represents a resource id argument to a function.""" @@ -8635,6 +8897,15 @@ def WriteFormat(self, filename): """Writes the command buffer format""" file = CHeaderWriter(filename) + # Forward declaration of a few enums used in constant argument + # to avoid including GL header files. + enum_defines = { + 'GL_SYNC_GPU_COMMANDS_COMPLETE': 0x9117, + } + file.Write('\n') + for enum in enum_defines: + file.Write("#define %s 0x%x\n" % (enum, enum_defines[enum])) + file.Write('\n') for func in self.functions: if True: #gen_cmd = func.GetInfo('gen_cmd')
diff --git a/gpu/command_buffer/client/gles2_c_lib_autogen.h b/gpu/command_buffer/client/gles2_c_lib_autogen.h index cd3bd7fd..0158cf6 100644 --- a/gpu/command_buffer/client/gles2_c_lib_autogen.h +++ b/gpu/command_buffer/client/gles2_c_lib_autogen.h
@@ -347,6 +347,9 @@ void GLES2GetFloatv(GLenum pname, GLfloat* params) { gles2::GetGLContext()->GetFloatv(pname, params); } +GLint GLES2GetFragDataLocation(GLuint program, const char* name) { + return gles2::GetGLContext()->GetFragDataLocation(program, name); +} void GLES2GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, @@ -1537,6 +1540,10 @@ reinterpret_cast<GLES2FunctionPointer>(glGetFloatv), }, { + "glGetFragDataLocation", + reinterpret_cast<GLES2FunctionPointer>(glGetFragDataLocation), + }, + { "glGetFramebufferAttachmentParameteriv", reinterpret_cast<GLES2FunctionPointer>( glGetFramebufferAttachmentParameteriv),
diff --git a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h index 8ba8b431..2b9cd8b9 100644 --- a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h +++ b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
@@ -744,6 +744,17 @@ } } +void GetFragDataLocation(GLuint program, + uint32_t name_bucket_id, + uint32_t location_shm_id, + uint32_t location_shm_offset) { + gles2::cmds::GetFragDataLocation* c = + GetCmdSpace<gles2::cmds::GetFragDataLocation>(); + if (c) { + c->Init(program, name_bucket_id, location_shm_id, location_shm_offset); + } +} + void GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname,
diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc index 6ad46f8..b4628a0 100644 --- a/gpu/command_buffer/client/gles2_implementation.cc +++ b/gpu/command_buffer/client/gles2_implementation.cc
@@ -1061,6 +1061,35 @@ return got_value; } +GLint GLES2Implementation::GetFragDataLocationHelper( + GLuint program, const char* name) { + typedef cmds::GetFragDataLocation::Result Result; + Result* result = GetResultAs<Result*>(); + if (!result) { + return -1; + } + *result = -1; + SetBucketAsCString(kResultBucketId, name); + helper_->GetFragDataLocation( + program, kResultBucketId, GetResultShmId(), GetResultShmOffset()); + WaitForCmd(); + helper_->SetBucketSize(kResultBucketId, 0); + return *result; +} + +GLint GLES2Implementation::GetFragDataLocation( + GLuint program, const char* name) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetFragDataLocation(" + << program << ", " << name << ")"); + TRACE_EVENT0("gpu", "GLES2::GetFragDataLocation"); + GLint loc = share_group_->program_info_manager()->GetFragDataLocation( + this, program, name); + GPU_CLIENT_LOG("returned " << loc); + CheckGLError(); + return loc; +} + void GLES2Implementation::LinkProgram(GLuint program) { GPU_CLIENT_SINGLE_THREAD_CHECK(); GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glLinkProgram(" << program << ")");
diff --git a/gpu/command_buffer/client/gles2_implementation.h b/gpu/command_buffer/client/gles2_implementation.h index a1b3621..470200e8 100644 --- a/gpu/command_buffer/client/gles2_implementation.h +++ b/gpu/command_buffer/client/gles2_implementation.h
@@ -213,6 +213,7 @@ void GetProgramInfoCHROMIUMHelper(GLuint program, std::vector<int8>* result); GLint GetAttribLocationHelper(GLuint program, const char* name); GLint GetUniformLocationHelper(GLuint program, const char* name); + GLint GetFragDataLocationHelper(GLuint program, const char* name); bool GetActiveAttribHelper( GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name);
diff --git a/gpu/command_buffer/client/gles2_implementation_autogen.h b/gpu/command_buffer/client/gles2_implementation_autogen.h index 0572358..b32dd445 100644 --- a/gpu/command_buffer/client/gles2_implementation_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_autogen.h
@@ -260,6 +260,8 @@ void GetFloatv(GLenum pname, GLfloat* params) override; +GLint GetFragDataLocation(GLuint program, const char* name) override; + void GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname,
diff --git a/gpu/command_buffer/client/gles2_implementation_impl_autogen.h b/gpu/command_buffer/client/gles2_implementation_impl_autogen.h index 65e38b1..90f91c5 100644 --- a/gpu/command_buffer/client/gles2_implementation_impl_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_impl_autogen.h
@@ -644,7 +644,7 @@ GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glFenceSync(" << GLES2Util::GetStringSyncCondition(condition) << ", " << flags << ")"); - if (condition != 0x9117) { + if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE) { SetGLError(GL_INVALID_ENUM, "glFenceSync", "condition GL_INVALID_ENUM"); return 0; }
diff --git a/gpu/command_buffer/client/gles2_implementation_unittest.cc b/gpu/command_buffer/client/gles2_implementation_unittest.cc index c69886ae..c88ba642 100644 --- a/gpu/command_buffer/client/gles2_implementation_unittest.cc +++ b/gpu/command_buffer/client/gles2_implementation_unittest.cc
@@ -896,100 +896,6 @@ EXPECT_EQ(precision4, 7); } -TEST_F(GLES2ImplementationTest, ShaderSource) { - const uint32 kBucketId = GLES2Implementation::kResultBucketId; - const GLuint kShaderId = 456; - const char* kString1 = "foobar"; - const char* kString2 = "barfoo"; - const size_t kString1Size = strlen(kString1) + 1; - const size_t kString2Size = strlen(kString2) + 1; - const size_t kHeaderSize = sizeof(GLint) * 3; - const size_t kSourceSize = kHeaderSize + kString1Size + kString2Size; - const size_t kPaddedHeaderSize = - transfer_buffer_->RoundToAlignment(kHeaderSize); - const size_t kPaddedString1Size = - transfer_buffer_->RoundToAlignment(kString1Size); - const size_t kPaddedString2Size = - transfer_buffer_->RoundToAlignment(kString2Size); - struct Cmds { - cmd::SetBucketSize set_bucket_size; - cmd::SetBucketData set_bucket_header; - cmd::SetToken set_token1; - cmd::SetBucketData set_bucket_data1; - cmd::SetToken set_token2; - cmd::SetBucketData set_bucket_data2; - cmd::SetToken set_token3; - cmds::ShaderSourceBucket shader_source_bucket; - cmd::SetBucketSize clear_bucket_size; - }; - - ExpectedMemoryInfo mem0 = GetExpectedMemory(kPaddedHeaderSize); - ExpectedMemoryInfo mem1 = GetExpectedMemory(kPaddedString1Size); - ExpectedMemoryInfo mem2 = GetExpectedMemory(kPaddedString2Size); - - Cmds expected; - expected.set_bucket_size.Init(kBucketId, kSourceSize); - expected.set_bucket_header.Init( - kBucketId, 0, kHeaderSize, mem0.id, mem0.offset); - expected.set_token1.Init(GetNextToken()); - expected.set_bucket_data1.Init( - kBucketId, kHeaderSize, kString1Size, mem1.id, mem1.offset); - expected.set_token2.Init(GetNextToken()); - expected.set_bucket_data2.Init( - kBucketId, kHeaderSize + kString1Size, kString2Size, mem2.id, - mem2.offset); - expected.set_token3.Init(GetNextToken()); - expected.shader_source_bucket.Init(kShaderId, kBucketId); - expected.clear_bucket_size.Init(kBucketId, 0); - const char* kStrings[] = { - kString1, - kString2, - }; - gl_->ShaderSource(kShaderId, 2, kStrings, NULL); - EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); -} - -TEST_F(GLES2ImplementationTest, ShaderSourceWithLength) { - const uint32 kBucketId = GLES2Implementation::kResultBucketId; - const GLuint kShaderId = 456; - const char* kString = "foobar******"; - const size_t kStringSize = 6; // We only need "foobar". - const size_t kHeaderSize = sizeof(GLint) * 2; - const size_t kSourceSize = kHeaderSize + kStringSize + 1; - const size_t kPaddedHeaderSize = - transfer_buffer_->RoundToAlignment(kHeaderSize); - const size_t kPaddedStringSize = - transfer_buffer_->RoundToAlignment(kStringSize + 1); - - struct Cmds { - cmd::SetBucketSize set_bucket_size; - cmd::SetBucketData set_bucket_header; - cmd::SetToken set_token1; - cmd::SetBucketData set_bucket_data; - cmd::SetToken set_token2; - cmds::ShaderSourceBucket shader_source_bucket; - cmd::SetBucketSize clear_bucket_size; - }; - - ExpectedMemoryInfo mem0 = GetExpectedMemory(kPaddedHeaderSize); - ExpectedMemoryInfo mem1 = GetExpectedMemory(kPaddedStringSize); - - Cmds expected; - expected.set_bucket_size.Init(kBucketId, kSourceSize); - expected.set_bucket_header.Init( - kBucketId, 0, kHeaderSize, mem0.id, mem0.offset); - expected.set_token1.Init(GetNextToken()); - expected.set_bucket_data.Init( - kBucketId, kHeaderSize, kStringSize + 1, mem1.id, mem1.offset); - expected.set_token2.Init(GetNextToken()); - expected.shader_source_bucket.Init(kShaderId, kBucketId); - expected.clear_bucket_size.Init(kBucketId, 0); - const char* kStrings[] = { kString }; - const GLint kLength[] = { kStringSize }; - gl_->ShaderSource(kShaderId, 1, kStrings, kLength); - EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); -} - TEST_F(GLES2ImplementationTest, GetShaderSource) { const uint32 kBucketId = GLES2Implementation::kResultBucketId; const GLuint kShaderId = 456;
diff --git a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h index 4d44ad7..845ab06 100644 --- a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h
@@ -23,7 +23,7 @@ gl_->AttachShader(1, 2); EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); } -// TODO: Implement unit test for BindAttribLocation +// TODO(zmo): Implement unit test for BindAttribLocation TEST_F(GLES2ImplementationTest, BindBuffer) { struct Cmds { @@ -309,8 +309,8 @@ gl_->CompileShader(1); EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); } -// TODO: Implement unit test for CompressedTexImage2D -// TODO: Implement unit test for CompressedTexSubImage2D +// TODO(zmo): Implement unit test for CompressedTexImage2D +// TODO(zmo): Implement unit test for CompressedTexSubImage2D TEST_F(GLES2ImplementationTest, CopyBufferSubData) { struct Cmds { @@ -738,10 +738,10 @@ EXPECT_EQ(kTransformFeedbacksStartId, ids[0]); EXPECT_EQ(kTransformFeedbacksStartId + 1, ids[1]); } -// TODO: Implement unit test for GetActiveAttrib -// TODO: Implement unit test for GetActiveUniform -// TODO: Implement unit test for GetAttachedShaders -// TODO: Implement unit test for GetAttribLocation +// TODO(zmo): Implement unit test for GetActiveAttrib +// TODO(zmo): Implement unit test for GetActiveUniform +// TODO(zmo): Implement unit test for GetAttachedShaders +// TODO(zmo): Implement unit test for GetAttribLocation TEST_F(GLES2ImplementationTest, GetBooleanv) { struct Cmds { @@ -793,6 +793,7 @@ EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); EXPECT_EQ(static_cast<Result::Type>(1), result); } +// TODO(zmo): Implement unit test for GetFragDataLocation TEST_F(GLES2ImplementationTest, GetFramebufferAttachmentParameteriv) { struct Cmds { @@ -866,7 +867,7 @@ EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); EXPECT_EQ(static_cast<Result::Type>(1), result); } -// TODO: Implement unit test for GetProgramInfoLog +// TODO(zmo): Implement unit test for GetProgramInfoLog TEST_F(GLES2ImplementationTest, GetRenderbufferParameteriv) { struct Cmds { @@ -935,8 +936,8 @@ EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); EXPECT_EQ(static_cast<Result::Type>(1), result); } -// TODO: Implement unit test for GetShaderInfoLog -// TODO: Implement unit test for GetShaderPrecisionFormat +// TODO(zmo): Implement unit test for GetShaderInfoLog +// TODO(zmo): Implement unit test for GetShaderPrecisionFormat TEST_F(GLES2ImplementationTest, GetTexParameterfv) { struct Cmds { @@ -971,9 +972,9 @@ EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); EXPECT_EQ(static_cast<Result::Type>(1), result); } -// TODO: Implement unit test for GetUniformfv -// TODO: Implement unit test for GetUniformiv -// TODO: Implement unit test for GetUniformLocation +// TODO(zmo): Implement unit test for GetUniformfv +// TODO(zmo): Implement unit test for GetUniformiv +// TODO(zmo): Implement unit test for GetUniformLocation TEST_F(GLES2ImplementationTest, GetVertexAttribfv) { struct Cmds { @@ -1404,6 +1405,93 @@ EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); } +TEST_F(GLES2ImplementationTest, ShaderSource) { + const uint32 kBucketId = GLES2Implementation::kResultBucketId; + const char* kString1 = "happy"; + const char* kString2 = "ending"; + const size_t kString1Size = ::strlen(kString1) + 1; + const size_t kString2Size = ::strlen(kString2) + 1; + const size_t kHeaderSize = sizeof(GLint) * 3; + const size_t kSourceSize = kHeaderSize + kString1Size + kString2Size; + const size_t kPaddedHeaderSize = + transfer_buffer_->RoundToAlignment(kHeaderSize); + const size_t kPaddedString1Size = + transfer_buffer_->RoundToAlignment(kString1Size); + const size_t kPaddedString2Size = + transfer_buffer_->RoundToAlignment(kString2Size); + struct Cmds { + cmd::SetBucketSize set_bucket_size; + cmd::SetBucketData set_bucket_header; + cmd::SetToken set_token1; + cmd::SetBucketData set_bucket_data1; + cmd::SetToken set_token2; + cmd::SetBucketData set_bucket_data2; + cmd::SetToken set_token3; + cmds::ShaderSourceBucket shader_source_bucket; + cmd::SetBucketSize clear_bucket_size; + }; + + ExpectedMemoryInfo mem0 = GetExpectedMemory(kPaddedHeaderSize); + ExpectedMemoryInfo mem1 = GetExpectedMemory(kPaddedString1Size); + ExpectedMemoryInfo mem2 = GetExpectedMemory(kPaddedString2Size); + + Cmds expected; + expected.set_bucket_size.Init(kBucketId, kSourceSize); + expected.set_bucket_header.Init(kBucketId, 0, kHeaderSize, mem0.id, + mem0.offset); + expected.set_token1.Init(GetNextToken()); + expected.set_bucket_data1.Init(kBucketId, kHeaderSize, kString1Size, mem1.id, + mem1.offset); + expected.set_token2.Init(GetNextToken()); + expected.set_bucket_data2.Init(kBucketId, kHeaderSize + kString1Size, + kString2Size, mem2.id, mem2.offset); + expected.set_token3.Init(GetNextToken()); + expected.shader_source_bucket.Init(1, kBucketId); + expected.clear_bucket_size.Init(kBucketId, 0); + const char* kStrings[] = {kString1, kString2}; + gl_->ShaderSource(1, 2, kStrings, NULL); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); +} + +TEST_F(GLES2ImplementationTest, ShaderSourceWithLength) { + const uint32 kBucketId = GLES2Implementation::kResultBucketId; + const char* kString = "foobar******"; + const size_t kStringSize = 6; // We only need "foobar". + const size_t kHeaderSize = sizeof(GLint) * 2; + const size_t kSourceSize = kHeaderSize + kStringSize + 1; + const size_t kPaddedHeaderSize = + transfer_buffer_->RoundToAlignment(kHeaderSize); + const size_t kPaddedStringSize = + transfer_buffer_->RoundToAlignment(kStringSize + 1); + struct Cmds { + cmd::SetBucketSize set_bucket_size; + cmd::SetBucketData set_bucket_header; + cmd::SetToken set_token1; + cmd::SetBucketData set_bucket_data; + cmd::SetToken set_token2; + cmds::ShaderSourceBucket shader_source_bucket; + cmd::SetBucketSize clear_bucket_size; + }; + + ExpectedMemoryInfo mem0 = GetExpectedMemory(kPaddedHeaderSize); + ExpectedMemoryInfo mem1 = GetExpectedMemory(kPaddedStringSize); + + Cmds expected; + expected.set_bucket_size.Init(kBucketId, kSourceSize); + expected.set_bucket_header.Init(kBucketId, 0, kHeaderSize, mem0.id, + mem0.offset); + expected.set_token1.Init(GetNextToken()); + expected.set_bucket_data.Init(kBucketId, kHeaderSize, kStringSize + 1, + mem1.id, mem1.offset); + expected.set_token2.Init(GetNextToken()); + expected.shader_source_bucket.Init(1, kBucketId); + expected.clear_bucket_size.Init(kBucketId, 0); + const char* kStrings[] = {kString}; + const GLint kLength[] = {kStringSize}; + gl_->ShaderSource(1, 1, kStrings, kLength); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); +} + TEST_F(GLES2ImplementationTest, StencilFunc) { struct Cmds { cmds::StencilFunc cmd; @@ -2447,7 +2535,7 @@ gl_->DeleteQueriesEXT(arraysize(ids), &ids[0]); EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); } -// TODO: Implement unit test for BeginQueryEXT +// TODO(zmo): Implement unit test for BeginQueryEXT TEST_F(GLES2ImplementationTest, BeginTransformFeedback) { struct Cmds { @@ -2470,8 +2558,8 @@ gl_->EndTransformFeedback(); EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); } -// TODO: Implement unit test for InsertEventMarkerEXT -// TODO: Implement unit test for PushGroupMarkerEXT +// TODO(zmo): Implement unit test for InsertEventMarkerEXT +// TODO(zmo): Implement unit test for PushGroupMarkerEXT TEST_F(GLES2ImplementationTest, PopGroupMarkerEXT) { struct Cmds { @@ -2534,7 +2622,7 @@ EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); EXPECT_TRUE(result); } -// TODO: Implement unit test for EnableFeatureCHROMIUM +// TODO(zmo): Implement unit test for EnableFeatureCHROMIUM TEST_F(GLES2ImplementationTest, ResizeCHROMIUM) { struct Cmds { @@ -2546,9 +2634,9 @@ gl_->ResizeCHROMIUM(1, 2, 3); EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); } -// TODO: Implement unit test for GetRequestableExtensionsCHROMIUM -// TODO: Implement unit test for CreateStreamTextureCHROMIUM -// TODO: Implement unit test for GetTranslatedShaderSourceANGLE +// TODO(zmo): Implement unit test for GetRequestableExtensionsCHROMIUM +// TODO(zmo): Implement unit test for CreateStreamTextureCHROMIUM +// TODO(zmo): Implement unit test for GetTranslatedShaderSourceANGLE TEST_F(GLES2ImplementationTest, TexImageIOSurface2DCHROMIUM) { struct Cmds { @@ -2593,8 +2681,8 @@ gl_->VertexAttribDivisorANGLE(1, 2); EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); } -// TODO: Implement unit test for GenMailboxCHROMIUM -// TODO: Implement unit test for BindUniformLocationCHROMIUM +// TODO(zmo): Implement unit test for GenMailboxCHROMIUM +// TODO(zmo): Implement unit test for BindUniformLocationCHROMIUM TEST_F(GLES2ImplementationTest, GenValuebuffersCHROMIUM) { GLuint ids[2] = { @@ -2749,7 +2837,7 @@ GL_GUILTY_CONTEXT_RESET_ARB); EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); } -// TODO: Implement unit test for InsertSyncPointCHROMIUM +// TODO(zmo): Implement unit test for InsertSyncPointCHROMIUM TEST_F(GLES2ImplementationTest, WaitSyncPointCHROMIUM) { struct Cmds {
diff --git a/gpu/command_buffer/client/gles2_interface_autogen.h b/gpu/command_buffer/client/gles2_interface_autogen.h index fe0da5b6..c15ae64 100644 --- a/gpu/command_buffer/client/gles2_interface_autogen.h +++ b/gpu/command_buffer/client/gles2_interface_autogen.h
@@ -188,6 +188,7 @@ GLint* params) = 0; virtual GLenum GetError() = 0; virtual void GetFloatv(GLenum pname, GLfloat* params) = 0; +virtual GLint GetFragDataLocation(GLuint program, const char* name) = 0; virtual void GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname,
diff --git a/gpu/command_buffer/client/gles2_interface_stub_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_autogen.h index 76e09b1..58de603a9 100644 --- a/gpu/command_buffer/client/gles2_interface_stub_autogen.h +++ b/gpu/command_buffer/client/gles2_interface_stub_autogen.h
@@ -185,6 +185,7 @@ void GetBufferParameteriv(GLenum target, GLenum pname, GLint* params) override; GLenum GetError() override; void GetFloatv(GLenum pname, GLfloat* params) override; +GLint GetFragDataLocation(GLuint program, const char* name) override; void GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname,
diff --git a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h index eddbe910..59dc75f 100644 --- a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h +++ b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h
@@ -297,6 +297,10 @@ } void GLES2InterfaceStub::GetFloatv(GLenum /* pname */, GLfloat* /* params */) { } +GLint GLES2InterfaceStub::GetFragDataLocation(GLuint /* program */, + const char* /* name */) { + return 0; +} void GLES2InterfaceStub::GetFramebufferAttachmentParameteriv( GLenum /* target */, GLenum /* attachment */,
diff --git a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h index d878d1ed..e7d2979 100644 --- a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h +++ b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h
@@ -185,6 +185,7 @@ void GetBufferParameteriv(GLenum target, GLenum pname, GLint* params) override; GLenum GetError() override; void GetFloatv(GLenum pname, GLfloat* params) override; +GLint GetFragDataLocation(GLuint program, const char* name) override; void GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname,
diff --git a/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h b/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h index deb7f84..26233392 100644 --- a/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h +++ b/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h
@@ -522,6 +522,12 @@ gl_->GetFloatv(pname, params); } +GLint GLES2TraceImplementation::GetFragDataLocation(GLuint program, + const char* name) { + TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::GetFragDataLocation"); + return gl_->GetFragDataLocation(program, name); +} + void GLES2TraceImplementation::GetFramebufferAttachmentParameteriv( GLenum target, GLenum attachment,
diff --git a/gpu/command_buffer/client/program_info_manager.cc b/gpu/command_buffer/client/program_info_manager.cc index f667d6d..e167e38d9 100644 --- a/gpu/command_buffer/client/program_info_manager.cc +++ b/gpu/command_buffer/client/program_info_manager.cc
@@ -4,9 +4,10 @@ #include "gpu/command_buffer/client/program_info_manager.h" -#include <map> +#include <string> #include "base/compiler_specific.h" +#include "base/containers/hash_tables.h" #include "base/synchronization/lock.h" #include "gpu/command_buffer/client/gles2_implementation.h" #include "gpu/command_buffer/common/gles2_cmd_utils.h" @@ -36,6 +37,10 @@ GLuint program, const char* name) override; + GLint GetFragDataLocation(GLES2Implementation* gl, + GLuint program, + const char* name) override; + bool GetActiveAttrib(GLES2Implementation* gl, GLuint program, GLuint index, @@ -85,6 +90,11 @@ return gl->GetUniformLocationHelper(program, name); } +GLint NonCachedProgramInfoManager::GetFragDataLocation( + GLES2Implementation* gl, GLuint program, const char* name) { + return gl->GetFragDataLocationHelper(program, name); +} + bool NonCachedProgramInfoManager::GetActiveAttrib( GLES2Implementation* gl, GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, @@ -123,6 +133,10 @@ GLuint program, const char* name) override; + GLint GetFragDataLocation(GLES2Implementation* gl, + GLuint program, + const char* name) override; + bool GetActiveAttrib(GLES2Implementation* gl, GLuint program, GLuint index, @@ -191,6 +205,9 @@ // Gets the location of a uniform by name. GLint GetUniformLocation(const std::string& name) const; + GLint GetFragDataLocation(const std::string& name) const; + void CacheFragDataLocation(const std::string& name, GLint loc); + bool GetProgramiv(GLenum pname, GLint* params); // Updates the program info after a successful link. @@ -213,14 +230,15 @@ // Uniform info by index. UniformInfoVector uniform_infos_; + base::hash_map<std::string, GLint> frag_data_locations_; + // This is true if glLinkProgram was successful last time it was called. bool link_status_; }; Program* GetProgramInfo(GLES2Implementation* gl, GLuint program); - // TODO(gman): Switch to a faster container. - typedef std::map<GLuint, Program> ProgramInfoMap; + typedef base::hash_map<GLuint, Program> ProgramInfoMap; ProgramInfoMap program_infos_; @@ -284,6 +302,20 @@ return -1; } +GLint CachedProgramInfoManager::Program::GetFragDataLocation( + const std::string& name) const { + base::hash_map<std::string, GLint>::const_iterator iter = + frag_data_locations_.find(name); + if (iter == frag_data_locations_.end()) + return -1; + return iter->second; +} + +void CachedProgramInfoManager::Program::CacheFragDataLocation( + const std::string& name, GLint loc) { + frag_data_locations_[name] = loc; +} + bool CachedProgramInfoManager::Program::GetProgramiv( GLenum pname, GLint* params) { switch (pname) { @@ -338,6 +370,7 @@ } attrib_infos_.clear(); uniform_infos_.clear(); + frag_data_locations_.clear(); max_attrib_name_length_ = 0; max_uniform_name_length_ = 0; const ProgramInput* inputs = LocalGetAs<const ProgramInput*>( @@ -459,6 +492,30 @@ return gl->GetUniformLocationHelper(program, name); } +GLint CachedProgramInfoManager::GetFragDataLocation( + GLES2Implementation* gl, GLuint program, const char* name) { + // TODO(zmo): make FragData locations part of the ProgramInfo that are + // fetched altogether from the service side. See crbug.com/452104. + { + base::AutoLock auto_lock(lock_); + Program* info = GetProgramInfo(gl, program); + if (info) { + GLint possible_loc = info->GetFragDataLocation(name); + if (possible_loc != -1) + return possible_loc; + } + } + GLint loc = gl->GetFragDataLocationHelper(program, name); + if (loc != -1) { + base::AutoLock auto_lock(lock_); + Program* info = GetProgramInfo(gl, program); + if (info) { + info->CacheFragDataLocation(name, loc); + } + } + return loc; +} + bool CachedProgramInfoManager::GetActiveAttrib( GLES2Implementation* gl, GLuint program, GLuint index, GLsizei bufsize, GLsizei* length,
diff --git a/gpu/command_buffer/client/program_info_manager.h b/gpu/command_buffer/client/program_info_manager.h index 099f182..81be345f 100644 --- a/gpu/command_buffer/client/program_info_manager.h +++ b/gpu/command_buffer/client/program_info_manager.h
@@ -33,6 +33,9 @@ virtual GLint GetUniformLocation( GLES2Implementation* gl, GLuint program, const char* name) = 0; + virtual GLint GetFragDataLocation( + GLES2Implementation* gl, GLuint program, const char* name) = 0; + virtual bool GetActiveAttrib( GLES2Implementation* gl, GLuint program, GLuint index, GLsizei bufsize, GLsizei* length,
diff --git a/gpu/command_buffer/cmd_buffer_functions.txt b/gpu/command_buffer/cmd_buffer_functions.txt index c595307..a744074 100644 --- a/gpu/command_buffer/cmd_buffer_functions.txt +++ b/gpu/command_buffer/cmd_buffer_functions.txt
@@ -82,6 +82,7 @@ GL_APICALL void GL_APIENTRY glGetBufferParameteriv (GLenumBufferTarget target, GLenumBufferParameter pname, GLint* params); GL_APICALL GLenum GL_APIENTRY glGetError (void); GL_APICALL void GL_APIENTRY glGetFloatv (GLenumGLState pname, GLfloat* params); +GL_APICALL GLint GL_APIENTRY glGetFragDataLocation (GLidProgram program, const char* name); GL_APICALL void GL_APIENTRY glGetFramebufferAttachmentParameteriv (GLenumFrameBufferTarget target, GLenumAttachment attachment, GLenumFrameBufferParameter pname, GLint* params); GL_APICALL void GL_APIENTRY glGetIntegerv (GLenumGLState pname, GLint* params); GL_APICALL void GL_APIENTRY glGetInternalformativ (GLenumRenderBufferTarget target, GLenumRenderBufferFormat format, GLenumRenderBufferParameter pname, GLsizei bufSize, GLint* params);
diff --git a/gpu/command_buffer/common/gles2_cmd_format_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_autogen.h index c57a48c4..00ee1b5 100644 --- a/gpu/command_buffer/common/gles2_cmd_format_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_format_autogen.h
@@ -11,6 +11,8 @@ #ifndef GPU_COMMAND_BUFFER_COMMON_GLES2_CMD_FORMAT_AUTOGEN_H_ #define GPU_COMMAND_BUFFER_COMMON_GLES2_CMD_FORMAT_AUTOGEN_H_ +#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117 + struct ActiveTexture { typedef ActiveTexture ValueType; static const CommandId kCmdId = kActiveTexture; @@ -2595,7 +2597,7 @@ gpu::CommandHeader header; uint32_t client_id; - static const uint32_t condition = 0x9117; + static const uint32_t condition = GL_SYNC_GPU_COMMANDS_COMPLETE; static const uint32_t flags = 0; }; @@ -3588,6 +3590,61 @@ static_assert(offsetof(GetFloatv, params_shm_offset) == 12, "offset of GetFloatv params_shm_offset should be 12"); +struct GetFragDataLocation { + typedef GetFragDataLocation ValueType; + static const CommandId kCmdId = kGetFragDataLocation; + static const cmd::ArgFlags kArgFlags = cmd::kFixed; + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + + typedef GLint Result; + + static uint32_t ComputeSize() { + return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT + } + + void SetHeader() { header.SetCmd<ValueType>(); } + + void Init(GLuint _program, + uint32_t _name_bucket_id, + uint32_t _location_shm_id, + uint32_t _location_shm_offset) { + SetHeader(); + program = _program; + name_bucket_id = _name_bucket_id; + location_shm_id = _location_shm_id; + location_shm_offset = _location_shm_offset; + } + + void* Set(void* cmd, + GLuint _program, + uint32_t _name_bucket_id, + uint32_t _location_shm_id, + uint32_t _location_shm_offset) { + static_cast<ValueType*>(cmd)->Init(_program, _name_bucket_id, + _location_shm_id, _location_shm_offset); + return NextCmdAddress<ValueType>(cmd); + } + + gpu::CommandHeader header; + uint32_t program; + uint32_t name_bucket_id; + uint32_t location_shm_id; + uint32_t location_shm_offset; +}; + +static_assert(sizeof(GetFragDataLocation) == 20, + "size of GetFragDataLocation should be 20"); +static_assert(offsetof(GetFragDataLocation, header) == 0, + "offset of GetFragDataLocation header should be 0"); +static_assert(offsetof(GetFragDataLocation, program) == 4, + "offset of GetFragDataLocation program should be 4"); +static_assert(offsetof(GetFragDataLocation, name_bucket_id) == 8, + "offset of GetFragDataLocation name_bucket_id should be 8"); +static_assert(offsetof(GetFragDataLocation, location_shm_id) == 12, + "offset of GetFragDataLocation location_shm_id should be 12"); +static_assert(offsetof(GetFragDataLocation, location_shm_offset) == 16, + "offset of GetFragDataLocation location_shm_offset should be 16"); + struct GetFramebufferAttachmentParameteriv { typedef GetFramebufferAttachmentParameteriv ValueType; static const CommandId kCmdId = kGetFramebufferAttachmentParameteriv;
diff --git a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h index 7f1e9917..5fc1672 100644 --- a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
@@ -1156,6 +1156,21 @@ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); } +TEST_F(GLES2FormatTest, GetFragDataLocation) { + cmds::GetFragDataLocation& cmd = *GetBufferAs<cmds::GetFragDataLocation>(); + void* next_cmd = + cmd.Set(&cmd, static_cast<GLuint>(11), static_cast<uint32_t>(12), + static_cast<uint32_t>(13), static_cast<uint32_t>(14)); + EXPECT_EQ(static_cast<uint32_t>(cmds::GetFragDataLocation::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + EXPECT_EQ(static_cast<GLuint>(11), cmd.program); + EXPECT_EQ(static_cast<uint32_t>(12), cmd.name_bucket_id); + EXPECT_EQ(static_cast<uint32_t>(13), cmd.location_shm_id); + EXPECT_EQ(static_cast<uint32_t>(14), cmd.location_shm_offset); + CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); +} + TEST_F(GLES2FormatTest, GetFramebufferAttachmentParameteriv) { cmds::GetFramebufferAttachmentParameteriv& cmd = *GetBufferAs<cmds::GetFramebufferAttachmentParameteriv>();
diff --git a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h index 0c999f4..6f90f73 100644 --- a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
@@ -92,187 +92,188 @@ OP(GetBufferParameteriv) /* 333 */ \ OP(GetError) /* 334 */ \ OP(GetFloatv) /* 335 */ \ - OP(GetFramebufferAttachmentParameteriv) /* 336 */ \ - OP(GetIntegerv) /* 337 */ \ - OP(GetInternalformativ) /* 338 */ \ - OP(GetProgramiv) /* 339 */ \ - OP(GetProgramInfoLog) /* 340 */ \ - OP(GetRenderbufferParameteriv) /* 341 */ \ - OP(GetSamplerParameterfv) /* 342 */ \ - OP(GetSamplerParameteriv) /* 343 */ \ - OP(GetShaderiv) /* 344 */ \ - OP(GetShaderInfoLog) /* 345 */ \ - OP(GetShaderPrecisionFormat) /* 346 */ \ - OP(GetShaderSource) /* 347 */ \ - OP(GetString) /* 348 */ \ - OP(GetTexParameterfv) /* 349 */ \ - OP(GetTexParameteriv) /* 350 */ \ - OP(GetUniformfv) /* 351 */ \ - OP(GetUniformiv) /* 352 */ \ - OP(GetUniformLocation) /* 353 */ \ - OP(GetVertexAttribfv) /* 354 */ \ - OP(GetVertexAttribiv) /* 355 */ \ - OP(GetVertexAttribPointerv) /* 356 */ \ - OP(Hint) /* 357 */ \ - OP(InvalidateFramebufferImmediate) /* 358 */ \ - OP(InvalidateSubFramebufferImmediate) /* 359 */ \ - OP(IsBuffer) /* 360 */ \ - OP(IsEnabled) /* 361 */ \ - OP(IsFramebuffer) /* 362 */ \ - OP(IsProgram) /* 363 */ \ - OP(IsRenderbuffer) /* 364 */ \ - OP(IsSampler) /* 365 */ \ - OP(IsShader) /* 366 */ \ - OP(IsSync) /* 367 */ \ - OP(IsTexture) /* 368 */ \ - OP(IsTransformFeedback) /* 369 */ \ - OP(LineWidth) /* 370 */ \ - OP(LinkProgram) /* 371 */ \ - OP(PauseTransformFeedback) /* 372 */ \ - OP(PixelStorei) /* 373 */ \ - OP(PolygonOffset) /* 374 */ \ - OP(ReadBuffer) /* 375 */ \ - OP(ReadPixels) /* 376 */ \ - OP(ReleaseShaderCompiler) /* 377 */ \ - OP(RenderbufferStorage) /* 378 */ \ - OP(ResumeTransformFeedback) /* 379 */ \ - OP(SampleCoverage) /* 380 */ \ - OP(SamplerParameterf) /* 381 */ \ - OP(SamplerParameterfvImmediate) /* 382 */ \ - OP(SamplerParameteri) /* 383 */ \ - OP(SamplerParameterivImmediate) /* 384 */ \ - OP(Scissor) /* 385 */ \ - OP(ShaderBinary) /* 386 */ \ - OP(ShaderSourceBucket) /* 387 */ \ - OP(StencilFunc) /* 388 */ \ - OP(StencilFuncSeparate) /* 389 */ \ - OP(StencilMask) /* 390 */ \ - OP(StencilMaskSeparate) /* 391 */ \ - OP(StencilOp) /* 392 */ \ - OP(StencilOpSeparate) /* 393 */ \ - OP(TexImage2D) /* 394 */ \ - OP(TexImage3D) /* 395 */ \ - OP(TexParameterf) /* 396 */ \ - OP(TexParameterfvImmediate) /* 397 */ \ - OP(TexParameteri) /* 398 */ \ - OP(TexParameterivImmediate) /* 399 */ \ - OP(TexStorage3D) /* 400 */ \ - OP(TexSubImage2D) /* 401 */ \ - OP(TexSubImage3D) /* 402 */ \ - OP(Uniform1f) /* 403 */ \ - OP(Uniform1fvImmediate) /* 404 */ \ - OP(Uniform1i) /* 405 */ \ - OP(Uniform1ivImmediate) /* 406 */ \ - OP(Uniform1ui) /* 407 */ \ - OP(Uniform1uivImmediate) /* 408 */ \ - OP(Uniform2f) /* 409 */ \ - OP(Uniform2fvImmediate) /* 410 */ \ - OP(Uniform2i) /* 411 */ \ - OP(Uniform2ivImmediate) /* 412 */ \ - OP(Uniform2ui) /* 413 */ \ - OP(Uniform2uivImmediate) /* 414 */ \ - OP(Uniform3f) /* 415 */ \ - OP(Uniform3fvImmediate) /* 416 */ \ - OP(Uniform3i) /* 417 */ \ - OP(Uniform3ivImmediate) /* 418 */ \ - OP(Uniform3ui) /* 419 */ \ - OP(Uniform3uivImmediate) /* 420 */ \ - OP(Uniform4f) /* 421 */ \ - OP(Uniform4fvImmediate) /* 422 */ \ - OP(Uniform4i) /* 423 */ \ - OP(Uniform4ivImmediate) /* 424 */ \ - OP(Uniform4ui) /* 425 */ \ - OP(Uniform4uivImmediate) /* 426 */ \ - OP(UniformMatrix2fvImmediate) /* 427 */ \ - OP(UniformMatrix2x3fvImmediate) /* 428 */ \ - OP(UniformMatrix2x4fvImmediate) /* 429 */ \ - OP(UniformMatrix3fvImmediate) /* 430 */ \ - OP(UniformMatrix3x2fvImmediate) /* 431 */ \ - OP(UniformMatrix3x4fvImmediate) /* 432 */ \ - OP(UniformMatrix4fvImmediate) /* 433 */ \ - OP(UniformMatrix4x2fvImmediate) /* 434 */ \ - OP(UniformMatrix4x3fvImmediate) /* 435 */ \ - OP(UseProgram) /* 436 */ \ - OP(ValidateProgram) /* 437 */ \ - OP(VertexAttrib1f) /* 438 */ \ - OP(VertexAttrib1fvImmediate) /* 439 */ \ - OP(VertexAttrib2f) /* 440 */ \ - OP(VertexAttrib2fvImmediate) /* 441 */ \ - OP(VertexAttrib3f) /* 442 */ \ - OP(VertexAttrib3fvImmediate) /* 443 */ \ - OP(VertexAttrib4f) /* 444 */ \ - OP(VertexAttrib4fvImmediate) /* 445 */ \ - OP(VertexAttribI4i) /* 446 */ \ - OP(VertexAttribI4ivImmediate) /* 447 */ \ - OP(VertexAttribI4ui) /* 448 */ \ - OP(VertexAttribI4uivImmediate) /* 449 */ \ - OP(VertexAttribIPointer) /* 450 */ \ - OP(VertexAttribPointer) /* 451 */ \ - OP(Viewport) /* 452 */ \ - OP(BlitFramebufferCHROMIUM) /* 453 */ \ - OP(RenderbufferStorageMultisampleCHROMIUM) /* 454 */ \ - OP(RenderbufferStorageMultisampleEXT) /* 455 */ \ - OP(FramebufferTexture2DMultisampleEXT) /* 456 */ \ - OP(TexStorage2DEXT) /* 457 */ \ - OP(GenQueriesEXTImmediate) /* 458 */ \ - OP(DeleteQueriesEXTImmediate) /* 459 */ \ - OP(BeginQueryEXT) /* 460 */ \ - OP(BeginTransformFeedback) /* 461 */ \ - OP(EndQueryEXT) /* 462 */ \ - OP(EndTransformFeedback) /* 463 */ \ - OP(InsertEventMarkerEXT) /* 464 */ \ - OP(PushGroupMarkerEXT) /* 465 */ \ - OP(PopGroupMarkerEXT) /* 466 */ \ - OP(GenVertexArraysOESImmediate) /* 467 */ \ - OP(DeleteVertexArraysOESImmediate) /* 468 */ \ - OP(IsVertexArrayOES) /* 469 */ \ - OP(BindVertexArrayOES) /* 470 */ \ - OP(SwapBuffers) /* 471 */ \ - OP(GetMaxValueInBufferCHROMIUM) /* 472 */ \ - OP(EnableFeatureCHROMIUM) /* 473 */ \ - OP(ResizeCHROMIUM) /* 474 */ \ - OP(GetRequestableExtensionsCHROMIUM) /* 475 */ \ - OP(RequestExtensionCHROMIUM) /* 476 */ \ - OP(GetProgramInfoCHROMIUM) /* 477 */ \ - OP(GetTranslatedShaderSourceANGLE) /* 478 */ \ - OP(PostSubBufferCHROMIUM) /* 479 */ \ - OP(TexImageIOSurface2DCHROMIUM) /* 480 */ \ - OP(CopyTextureCHROMIUM) /* 481 */ \ - OP(DrawArraysInstancedANGLE) /* 482 */ \ - OP(DrawElementsInstancedANGLE) /* 483 */ \ - OP(VertexAttribDivisorANGLE) /* 484 */ \ - OP(GenMailboxCHROMIUM) /* 485 */ \ - OP(ProduceTextureCHROMIUMImmediate) /* 486 */ \ - OP(ProduceTextureDirectCHROMIUMImmediate) /* 487 */ \ - OP(ConsumeTextureCHROMIUMImmediate) /* 488 */ \ - OP(CreateAndConsumeTextureCHROMIUMImmediate) /* 489 */ \ - OP(BindUniformLocationCHROMIUMBucket) /* 490 */ \ - OP(GenValuebuffersCHROMIUMImmediate) /* 491 */ \ - OP(DeleteValuebuffersCHROMIUMImmediate) /* 492 */ \ - OP(IsValuebufferCHROMIUM) /* 493 */ \ - OP(BindValuebufferCHROMIUM) /* 494 */ \ - OP(SubscribeValueCHROMIUM) /* 495 */ \ - OP(PopulateSubscribedValuesCHROMIUM) /* 496 */ \ - OP(UniformValuebufferCHROMIUM) /* 497 */ \ - OP(BindTexImage2DCHROMIUM) /* 498 */ \ - OP(ReleaseTexImage2DCHROMIUM) /* 499 */ \ - OP(TraceBeginCHROMIUM) /* 500 */ \ - OP(TraceEndCHROMIUM) /* 501 */ \ - OP(AsyncTexSubImage2DCHROMIUM) /* 502 */ \ - OP(AsyncTexImage2DCHROMIUM) /* 503 */ \ - OP(WaitAsyncTexImage2DCHROMIUM) /* 504 */ \ - OP(WaitAllAsyncTexImage2DCHROMIUM) /* 505 */ \ - OP(DiscardFramebufferEXTImmediate) /* 506 */ \ - OP(LoseContextCHROMIUM) /* 507 */ \ - OP(InsertSyncPointCHROMIUM) /* 508 */ \ - OP(WaitSyncPointCHROMIUM) /* 509 */ \ - OP(DrawBuffersEXTImmediate) /* 510 */ \ - OP(DiscardBackbufferCHROMIUM) /* 511 */ \ - OP(ScheduleOverlayPlaneCHROMIUM) /* 512 */ \ - OP(SwapInterval) /* 513 */ \ - OP(MatrixLoadfCHROMIUMImmediate) /* 514 */ \ - OP(MatrixLoadIdentityCHROMIUM) /* 515 */ \ - OP(BlendBarrierKHR) /* 516 */ + OP(GetFragDataLocation) /* 336 */ \ + OP(GetFramebufferAttachmentParameteriv) /* 337 */ \ + OP(GetIntegerv) /* 338 */ \ + OP(GetInternalformativ) /* 339 */ \ + OP(GetProgramiv) /* 340 */ \ + OP(GetProgramInfoLog) /* 341 */ \ + OP(GetRenderbufferParameteriv) /* 342 */ \ + OP(GetSamplerParameterfv) /* 343 */ \ + OP(GetSamplerParameteriv) /* 344 */ \ + OP(GetShaderiv) /* 345 */ \ + OP(GetShaderInfoLog) /* 346 */ \ + OP(GetShaderPrecisionFormat) /* 347 */ \ + OP(GetShaderSource) /* 348 */ \ + OP(GetString) /* 349 */ \ + OP(GetTexParameterfv) /* 350 */ \ + OP(GetTexParameteriv) /* 351 */ \ + OP(GetUniformfv) /* 352 */ \ + OP(GetUniformiv) /* 353 */ \ + OP(GetUniformLocation) /* 354 */ \ + OP(GetVertexAttribfv) /* 355 */ \ + OP(GetVertexAttribiv) /* 356 */ \ + OP(GetVertexAttribPointerv) /* 357 */ \ + OP(Hint) /* 358 */ \ + OP(InvalidateFramebufferImmediate) /* 359 */ \ + OP(InvalidateSubFramebufferImmediate) /* 360 */ \ + OP(IsBuffer) /* 361 */ \ + OP(IsEnabled) /* 362 */ \ + OP(IsFramebuffer) /* 363 */ \ + OP(IsProgram) /* 364 */ \ + OP(IsRenderbuffer) /* 365 */ \ + OP(IsSampler) /* 366 */ \ + OP(IsShader) /* 367 */ \ + OP(IsSync) /* 368 */ \ + OP(IsTexture) /* 369 */ \ + OP(IsTransformFeedback) /* 370 */ \ + OP(LineWidth) /* 371 */ \ + OP(LinkProgram) /* 372 */ \ + OP(PauseTransformFeedback) /* 373 */ \ + OP(PixelStorei) /* 374 */ \ + OP(PolygonOffset) /* 375 */ \ + OP(ReadBuffer) /* 376 */ \ + OP(ReadPixels) /* 377 */ \ + OP(ReleaseShaderCompiler) /* 378 */ \ + OP(RenderbufferStorage) /* 379 */ \ + OP(ResumeTransformFeedback) /* 380 */ \ + OP(SampleCoverage) /* 381 */ \ + OP(SamplerParameterf) /* 382 */ \ + OP(SamplerParameterfvImmediate) /* 383 */ \ + OP(SamplerParameteri) /* 384 */ \ + OP(SamplerParameterivImmediate) /* 385 */ \ + OP(Scissor) /* 386 */ \ + OP(ShaderBinary) /* 387 */ \ + OP(ShaderSourceBucket) /* 388 */ \ + OP(StencilFunc) /* 389 */ \ + OP(StencilFuncSeparate) /* 390 */ \ + OP(StencilMask) /* 391 */ \ + OP(StencilMaskSeparate) /* 392 */ \ + OP(StencilOp) /* 393 */ \ + OP(StencilOpSeparate) /* 394 */ \ + OP(TexImage2D) /* 395 */ \ + OP(TexImage3D) /* 396 */ \ + OP(TexParameterf) /* 397 */ \ + OP(TexParameterfvImmediate) /* 398 */ \ + OP(TexParameteri) /* 399 */ \ + OP(TexParameterivImmediate) /* 400 */ \ + OP(TexStorage3D) /* 401 */ \ + OP(TexSubImage2D) /* 402 */ \ + OP(TexSubImage3D) /* 403 */ \ + OP(Uniform1f) /* 404 */ \ + OP(Uniform1fvImmediate) /* 405 */ \ + OP(Uniform1i) /* 406 */ \ + OP(Uniform1ivImmediate) /* 407 */ \ + OP(Uniform1ui) /* 408 */ \ + OP(Uniform1uivImmediate) /* 409 */ \ + OP(Uniform2f) /* 410 */ \ + OP(Uniform2fvImmediate) /* 411 */ \ + OP(Uniform2i) /* 412 */ \ + OP(Uniform2ivImmediate) /* 413 */ \ + OP(Uniform2ui) /* 414 */ \ + OP(Uniform2uivImmediate) /* 415 */ \ + OP(Uniform3f) /* 416 */ \ + OP(Uniform3fvImmediate) /* 417 */ \ + OP(Uniform3i) /* 418 */ \ + OP(Uniform3ivImmediate) /* 419 */ \ + OP(Uniform3ui) /* 420 */ \ + OP(Uniform3uivImmediate) /* 421 */ \ + OP(Uniform4f) /* 422 */ \ + OP(Uniform4fvImmediate) /* 423 */ \ + OP(Uniform4i) /* 424 */ \ + OP(Uniform4ivImmediate) /* 425 */ \ + OP(Uniform4ui) /* 426 */ \ + OP(Uniform4uivImmediate) /* 427 */ \ + OP(UniformMatrix2fvImmediate) /* 428 */ \ + OP(UniformMatrix2x3fvImmediate) /* 429 */ \ + OP(UniformMatrix2x4fvImmediate) /* 430 */ \ + OP(UniformMatrix3fvImmediate) /* 431 */ \ + OP(UniformMatrix3x2fvImmediate) /* 432 */ \ + OP(UniformMatrix3x4fvImmediate) /* 433 */ \ + OP(UniformMatrix4fvImmediate) /* 434 */ \ + OP(UniformMatrix4x2fvImmediate) /* 435 */ \ + OP(UniformMatrix4x3fvImmediate) /* 436 */ \ + OP(UseProgram) /* 437 */ \ + OP(ValidateProgram) /* 438 */ \ + OP(VertexAttrib1f) /* 439 */ \ + OP(VertexAttrib1fvImmediate) /* 440 */ \ + OP(VertexAttrib2f) /* 441 */ \ + OP(VertexAttrib2fvImmediate) /* 442 */ \ + OP(VertexAttrib3f) /* 443 */ \ + OP(VertexAttrib3fvImmediate) /* 444 */ \ + OP(VertexAttrib4f) /* 445 */ \ + OP(VertexAttrib4fvImmediate) /* 446 */ \ + OP(VertexAttribI4i) /* 447 */ \ + OP(VertexAttribI4ivImmediate) /* 448 */ \ + OP(VertexAttribI4ui) /* 449 */ \ + OP(VertexAttribI4uivImmediate) /* 450 */ \ + OP(VertexAttribIPointer) /* 451 */ \ + OP(VertexAttribPointer) /* 452 */ \ + OP(Viewport) /* 453 */ \ + OP(BlitFramebufferCHROMIUM) /* 454 */ \ + OP(RenderbufferStorageMultisampleCHROMIUM) /* 455 */ \ + OP(RenderbufferStorageMultisampleEXT) /* 456 */ \ + OP(FramebufferTexture2DMultisampleEXT) /* 457 */ \ + OP(TexStorage2DEXT) /* 458 */ \ + OP(GenQueriesEXTImmediate) /* 459 */ \ + OP(DeleteQueriesEXTImmediate) /* 460 */ \ + OP(BeginQueryEXT) /* 461 */ \ + OP(BeginTransformFeedback) /* 462 */ \ + OP(EndQueryEXT) /* 463 */ \ + OP(EndTransformFeedback) /* 464 */ \ + OP(InsertEventMarkerEXT) /* 465 */ \ + OP(PushGroupMarkerEXT) /* 466 */ \ + OP(PopGroupMarkerEXT) /* 467 */ \ + OP(GenVertexArraysOESImmediate) /* 468 */ \ + OP(DeleteVertexArraysOESImmediate) /* 469 */ \ + OP(IsVertexArrayOES) /* 470 */ \ + OP(BindVertexArrayOES) /* 471 */ \ + OP(SwapBuffers) /* 472 */ \ + OP(GetMaxValueInBufferCHROMIUM) /* 473 */ \ + OP(EnableFeatureCHROMIUM) /* 474 */ \ + OP(ResizeCHROMIUM) /* 475 */ \ + OP(GetRequestableExtensionsCHROMIUM) /* 476 */ \ + OP(RequestExtensionCHROMIUM) /* 477 */ \ + OP(GetProgramInfoCHROMIUM) /* 478 */ \ + OP(GetTranslatedShaderSourceANGLE) /* 479 */ \ + OP(PostSubBufferCHROMIUM) /* 480 */ \ + OP(TexImageIOSurface2DCHROMIUM) /* 481 */ \ + OP(CopyTextureCHROMIUM) /* 482 */ \ + OP(DrawArraysInstancedANGLE) /* 483 */ \ + OP(DrawElementsInstancedANGLE) /* 484 */ \ + OP(VertexAttribDivisorANGLE) /* 485 */ \ + OP(GenMailboxCHROMIUM) /* 486 */ \ + OP(ProduceTextureCHROMIUMImmediate) /* 487 */ \ + OP(ProduceTextureDirectCHROMIUMImmediate) /* 488 */ \ + OP(ConsumeTextureCHROMIUMImmediate) /* 489 */ \ + OP(CreateAndConsumeTextureCHROMIUMImmediate) /* 490 */ \ + OP(BindUniformLocationCHROMIUMBucket) /* 491 */ \ + OP(GenValuebuffersCHROMIUMImmediate) /* 492 */ \ + OP(DeleteValuebuffersCHROMIUMImmediate) /* 493 */ \ + OP(IsValuebufferCHROMIUM) /* 494 */ \ + OP(BindValuebufferCHROMIUM) /* 495 */ \ + OP(SubscribeValueCHROMIUM) /* 496 */ \ + OP(PopulateSubscribedValuesCHROMIUM) /* 497 */ \ + OP(UniformValuebufferCHROMIUM) /* 498 */ \ + OP(BindTexImage2DCHROMIUM) /* 499 */ \ + OP(ReleaseTexImage2DCHROMIUM) /* 500 */ \ + OP(TraceBeginCHROMIUM) /* 501 */ \ + OP(TraceEndCHROMIUM) /* 502 */ \ + OP(AsyncTexSubImage2DCHROMIUM) /* 503 */ \ + OP(AsyncTexImage2DCHROMIUM) /* 504 */ \ + OP(WaitAsyncTexImage2DCHROMIUM) /* 505 */ \ + OP(WaitAllAsyncTexImage2DCHROMIUM) /* 506 */ \ + OP(DiscardFramebufferEXTImmediate) /* 507 */ \ + OP(LoseContextCHROMIUM) /* 508 */ \ + OP(InsertSyncPointCHROMIUM) /* 509 */ \ + OP(WaitSyncPointCHROMIUM) /* 510 */ \ + OP(DrawBuffersEXTImmediate) /* 511 */ \ + OP(DiscardBackbufferCHROMIUM) /* 512 */ \ + OP(ScheduleOverlayPlaneCHROMIUM) /* 513 */ \ + OP(SwapInterval) /* 514 */ \ + OP(MatrixLoadfCHROMIUMImmediate) /* 515 */ \ + OP(MatrixLoadIdentityCHROMIUM) /* 516 */ \ + OP(BlendBarrierKHR) /* 517 */ enum CommandId { kStartPoint = cmd::kLastCommonId, // All GLES2 commands start after this.
diff --git a/gpu/command_buffer/common/gles2_cmd_utils.cc b/gpu/command_buffer/common/gles2_cmd_utils.cc index 6a483f6..638245b7 100644 --- a/gpu/command_buffer/common/gles2_cmd_utils.cc +++ b/gpu/command_buffer/common/gles2_cmd_utils.cc
@@ -791,6 +791,8 @@ size_t* array_pos, int* element_index, bool* getting_array) { + if (name.empty()) + return false; bool getting_array_location = false; size_t open_pos = std::string::npos; base::CheckedNumeric<int> index = 0;
diff --git a/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h b/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h index 765cce68..393ee43 100644 --- a/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h
@@ -5094,7 +5094,7 @@ std::string GLES2Util::GetStringSyncCondition(uint32_t value) { static const EnumToString string_table[] = { - {0x9117, "0x9117"}, + {GL_SYNC_GPU_COMMANDS_COMPLETE, "GL_SYNC_GPU_COMMANDS_COMPLETE"}, }; return GLES2Util::GetQualifiedEnumString(string_table, arraysize(string_table), value);
diff --git a/gpu/command_buffer/common/gles2_cmd_utils_unittest.cc b/gpu/command_buffer/common/gles2_cmd_utils_unittest.cc index 2b1c93e..58a6c38 100644 --- a/gpu/command_buffer/common/gles2_cmd_utils_unittest.cc +++ b/gpu/command_buffer/common/gles2_cmd_utils_unittest.cc
@@ -390,6 +390,7 @@ CheckParseUniformName("u_name[03][02]", true, 10u, 2, true); CheckParseUniformName("u_name[30][20]", true, 10u, 20, true); CheckParseUniformName("u_name[030][020]", true, 11u, 20, true); + CheckParseUniformName("", false, std::string::npos, 0, false); } } // namespace gles2
diff --git a/gpu/command_buffer/common/time.h b/gpu/command_buffer/common/time.h index e4eb942..e58145b 100644 --- a/gpu/command_buffer/common/time.h +++ b/gpu/command_buffer/common/time.h
@@ -12,7 +12,7 @@ namespace gpu { inline uint64 MicrosecondsSinceOriginOfTime() { - return (base::TimeTicks::HighResNow() - base::TimeTicks()).InMicroseconds(); + return (base::TimeTicks::Now() - base::TimeTicks()).InMicroseconds(); } } // namespace gpu
diff --git a/gpu/command_buffer/service/async_pixel_transfer_manager_egl.cc b/gpu/command_buffer/service/async_pixel_transfer_manager_egl.cc index 34e3a37..4b87938 100644 --- a/gpu/command_buffer/service/async_pixel_transfer_manager_egl.cc +++ b/gpu/command_buffer/service/async_pixel_transfer_manager_egl.cc
@@ -256,7 +256,7 @@ base::TimeTicks begin_time; if (texture_upload_stats.get()) - begin_time = base::TimeTicks::HighResNow(); + begin_time = base::TimeTicks::Now(); { TRACE_EVENT0("gpu", "glTexImage2D no data"); @@ -291,8 +291,7 @@ DCHECK(CHECK_GL()); if (texture_upload_stats.get()) { - texture_upload_stats->AddUpload(base::TimeTicks::HighResNow() - - begin_time); + texture_upload_stats->AddUpload(base::TimeTicks::Now() - begin_time); } } @@ -314,7 +313,7 @@ base::TimeTicks begin_time; if (texture_upload_stats.get()) - begin_time = base::TimeTicks::HighResNow(); + begin_time = base::TimeTicks::Now(); if (!thread_texture_id_) { TRACE_EVENT0("gpu", "glEGLImageTargetTexture2DOES"); @@ -335,8 +334,7 @@ DCHECK(CHECK_GL()); if (texture_upload_stats.get()) { - texture_upload_stats->AddUpload(base::TimeTicks::HighResNow() - - begin_time); + texture_upload_stats->AddUpload(base::TimeTicks::Now() - begin_time); } } @@ -641,7 +639,7 @@ void* data = mem_params.GetDataAddress(); base::TimeTicks begin_time; if (shared_state_->texture_upload_stats.get()) - begin_time = base::TimeTicks::HighResNow(); + begin_time = base::TimeTicks::Now(); { TRACE_EVENT0("gpu", "glTexSubImage2D"); // Note we use define_params_ instead of tex_params. @@ -650,7 +648,7 @@ } if (shared_state_->texture_upload_stats.get()) { shared_state_->texture_upload_stats - ->AddUpload(base::TimeTicks::HighResNow() - begin_time); + ->AddUpload(base::TimeTicks::Now() - begin_time); } DCHECK(CHECK_GL());
diff --git a/gpu/command_buffer/service/async_pixel_transfer_manager_idle.cc b/gpu/command_buffer/service/async_pixel_transfer_manager_idle.cc index 61db3b68..de92c0c 100644 --- a/gpu/command_buffer/service/async_pixel_transfer_manager_idle.cc +++ b/gpu/command_buffer/service/async_pixel_transfer_manager_idle.cc
@@ -144,7 +144,7 @@ void* data = mem_params.GetDataAddress(); - base::TimeTicks begin_time(base::TimeTicks::HighResNow()); + base::TimeTicks begin_time(base::TimeTicks::Now()); gfx::ScopedTextureBinder texture_binder(tex_params.target, texture_id_); { @@ -165,7 +165,7 @@ transfer_in_progress_ = false; shared_state_->texture_upload_count++; shared_state_->total_texture_upload_time += - base::TimeTicks::HighResNow() - begin_time; + base::TimeTicks::Now() - begin_time; // The texture is already fully bound so just call it now. bind_callback.Run(); @@ -180,7 +180,7 @@ void* data = mem_params.GetDataAddress(); - base::TimeTicks begin_time(base::TimeTicks::HighResNow()); + base::TimeTicks begin_time(base::TimeTicks::Now()); gfx::ScopedTextureBinder texture_binder(tex_params.target, texture_id_); // If it's a full texture update, use glTexImage2D as it's faster. @@ -220,7 +220,7 @@ transfer_in_progress_ = false; shared_state_->texture_upload_count++; shared_state_->total_texture_upload_time += - base::TimeTicks::HighResNow() - begin_time; + base::TimeTicks::Now() - begin_time; } AsyncPixelTransferManagerIdle::Task::Task(
diff --git a/gpu/command_buffer/service/async_pixel_transfer_manager_share_group.cc b/gpu/command_buffer/service/async_pixel_transfer_manager_share_group.cc index b6506bfb..4f85e33 100644 --- a/gpu/command_buffer/service/async_pixel_transfer_manager_share_group.cc +++ b/gpu/command_buffer/service/async_pixel_transfer_manager_share_group.cc
@@ -293,7 +293,7 @@ base::TimeTicks begin_time; if (texture_upload_stats.get()) - begin_time = base::TimeTicks::HighResNow(); + begin_time = base::TimeTicks::Now(); void* data = mem_params.GetDataAddress(); @@ -312,8 +312,7 @@ } if (texture_upload_stats.get()) { - texture_upload_stats->AddUpload(base::TimeTicks::HighResNow() - - begin_time); + texture_upload_stats->AddUpload(base::TimeTicks::Now() - begin_time); } } @@ -331,7 +330,7 @@ base::TimeTicks begin_time; if (texture_upload_stats.get()) - begin_time = base::TimeTicks::HighResNow(); + begin_time = base::TimeTicks::Now(); void* data = mem_params.GetDataAddress(); { @@ -349,8 +348,7 @@ } if (texture_upload_stats.get()) { - texture_upload_stats->AddUpload(base::TimeTicks::HighResNow() - - begin_time); + texture_upload_stats->AddUpload(base::TimeTicks::Now() - begin_time); } }
diff --git a/gpu/command_buffer/service/async_pixel_transfer_manager_sync.cc b/gpu/command_buffer/service/async_pixel_transfer_manager_sync.cc index 4bc2ba2..589598b 100644 --- a/gpu/command_buffer/service/async_pixel_transfer_manager_sync.cc +++ b/gpu/command_buffer/service/async_pixel_transfer_manager_sync.cc
@@ -45,7 +45,7 @@ // Save the define params to return later during deferred // binding of the transfer texture. void* data = mem_params.GetDataAddress(); - base::TimeTicks begin_time(base::TimeTicks::HighResNow()); + base::TimeTicks begin_time(base::TimeTicks::Now()); glTexImage2D( tex_params.target, tex_params.level, @@ -58,7 +58,7 @@ data); shared_state_->texture_upload_count++; shared_state_->total_texture_upload_time += - base::TimeTicks::HighResNow() - begin_time; + base::TimeTicks::Now() - begin_time; // The texture is already fully bound so just call it now. bind_callback.Run(); } @@ -67,7 +67,7 @@ const AsyncTexSubImage2DParams& tex_params, const AsyncMemoryParams& mem_params) { void* data = mem_params.GetDataAddress(); - base::TimeTicks begin_time(base::TimeTicks::HighResNow()); + base::TimeTicks begin_time(base::TimeTicks::Now()); glTexSubImage2D( tex_params.target, tex_params.level, @@ -80,7 +80,7 @@ data); shared_state_->texture_upload_count++; shared_state_->total_texture_upload_time += - base::TimeTicks::HighResNow() - begin_time; + base::TimeTicks::Now() - begin_time; } bool AsyncPixelTransferDelegateSync::TransferIsInProgress() {
diff --git a/gpu/command_buffer/service/common_decoder.cc b/gpu/command_buffer/service/common_decoder.cc index 86a37ba..f40c721 100644 --- a/gpu/command_buffer/service/common_decoder.cc +++ b/gpu/command_buffer/service/common_decoder.cc
@@ -7,6 +7,19 @@ namespace gpu { +const CommonDecoder::CommandInfo CommonDecoder::command_info[] = { +#define COMMON_COMMAND_BUFFER_CMD_OP(name) \ + { \ + &CommonDecoder::Handle##name, cmd::name::kArgFlags, \ + cmd::name::cmd_flags, \ + sizeof(cmd::name) / sizeof(CommandBufferEntry) - 1, \ + } \ + , /* NOLINT */ + COMMON_COMMAND_BUFFER_CMDS(COMMON_COMMAND_BUFFER_CMD_OP) + #undef COMMON_COMMAND_BUFFER_CMD_OP +}; + + CommonDecoder::Bucket::Bucket() : size_(0) {} CommonDecoder::Bucket::~Bucket() {} @@ -108,29 +121,6 @@ return static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))); } -// TODO(vmiura): Looks like this g_command_info is duplicated in -// common_decoder.cc -// and gles2_cmd_decoder.cc. Fix it! - -// A struct to hold info about each command. -struct CommandInfo { - uint8 arg_flags; // How to handle the arguments for this command - uint8 cmd_flags; // How to handle this command - uint16 arg_count; // How many arguments are expected for this command. -}; - -// A table of CommandInfo for all the commands. -const CommandInfo g_command_info[] = { - #define COMMON_COMMAND_BUFFER_CMD_OP(name) { \ - cmd::name::kArgFlags, \ - cmd::name::cmd_flags, \ - sizeof(cmd::name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */ - - COMMON_COMMAND_BUFFER_CMDS(COMMON_COMMAND_BUFFER_CMD_OP) - - #undef COMMON_COMMAND_BUFFER_CMD_OP -}; - } // anonymous namespace. // Decode command with its arguments, and call the corresponding method. @@ -141,24 +131,14 @@ unsigned int command, unsigned int arg_count, const void* cmd_data) { - if (command < arraysize(g_command_info)) { - const CommandInfo& info = g_command_info[command]; + if (command < arraysize(command_info)) { + const CommandInfo& info = command_info[command]; unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count); if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) || (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) { uint32 immediate_data_size = (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT - switch (command) { - #define COMMON_COMMAND_BUFFER_CMD_OP(name) \ - case cmd::name::kCmdId: \ - return Handle ## name( \ - immediate_data_size, \ - *static_cast<const cmd::name*>(cmd_data)); \ - - COMMON_COMMAND_BUFFER_CMDS(COMMON_COMMAND_BUFFER_CMD_OP) - - #undef COMMON_COMMAND_BUFFER_CMD_OP - } + return (this->*info.cmd_handler)(immediate_data_size, cmd_data); } else { return error::kInvalidArguments; } @@ -168,20 +148,23 @@ error::Error CommonDecoder::HandleNoop( uint32 immediate_data_size, - const cmd::Noop& args) { + const void* cmd_data) { return error::kNoError; } error::Error CommonDecoder::HandleSetToken( uint32 immediate_data_size, - const cmd::SetToken& args) { + const void* cmd_data) { + const cmd::SetToken& args = *static_cast<const cmd::SetToken*>(cmd_data); engine_->set_token(args.token); return error::kNoError; } error::Error CommonDecoder::HandleSetBucketSize( uint32 immediate_data_size, - const cmd::SetBucketSize& args) { + const void* cmd_data) { + const cmd::SetBucketSize& args = + *static_cast<const cmd::SetBucketSize*>(cmd_data); uint32 bucket_id = args.bucket_id; uint32 size = args.size; @@ -192,7 +175,9 @@ error::Error CommonDecoder::HandleSetBucketData( uint32 immediate_data_size, - const cmd::SetBucketData& args) { + const void* cmd_data) { + const cmd::SetBucketData& args = + *static_cast<const cmd::SetBucketData*>(cmd_data); uint32 bucket_id = args.bucket_id; uint32 offset = args.offset; uint32 size = args.size; @@ -214,7 +199,9 @@ error::Error CommonDecoder::HandleSetBucketDataImmediate( uint32 immediate_data_size, - const cmd::SetBucketDataImmediate& args) { + const void* cmd_data) { + const cmd::SetBucketDataImmediate& args = + *static_cast<const cmd::SetBucketDataImmediate*>(cmd_data); const void* data = GetImmediateDataAs<const void*>(args); uint32 bucket_id = args.bucket_id; uint32 offset = args.offset; @@ -234,7 +221,9 @@ error::Error CommonDecoder::HandleGetBucketStart( uint32 immediate_data_size, - const cmd::GetBucketStart& args) { + const void* cmd_data) { + const cmd::GetBucketStart& args = + *static_cast<const cmd::GetBucketStart*>(cmd_data); uint32 bucket_id = args.bucket_id; uint32* result = GetSharedMemoryAs<uint32*>( args.result_memory_id, args.result_memory_offset, sizeof(*result)); @@ -271,7 +260,9 @@ error::Error CommonDecoder::HandleGetBucketData( uint32 immediate_data_size, - const cmd::GetBucketData& args) { + const void* cmd_data) { + const cmd::GetBucketData& args = + *static_cast<const cmd::GetBucketData*>(cmd_data); uint32 bucket_id = args.bucket_id; uint32 offset = args.offset; uint32 size = args.size;
diff --git a/gpu/command_buffer/service/common_decoder.h b/gpu/command_buffer/service/common_decoder.h index aaf860f..fc9ecf2 100644 --- a/gpu/command_buffer/service/common_decoder.h +++ b/gpu/command_buffer/service/common_decoder.h
@@ -155,9 +155,7 @@ // Generate a member function prototype for each command in an automated and // typesafe way. #define COMMON_COMMAND_BUFFER_CMD_OP(name) \ - error::Error Handle##name( \ - uint32 immediate_data_size, \ - const cmd::name& args); \ + error::Error Handle##name(uint32 immediate_data_size, const void* data); COMMON_COMMAND_BUFFER_CMDS(COMMON_COMMAND_BUFFER_CMD_OP) @@ -167,6 +165,22 @@ typedef std::map<uint32, linked_ptr<Bucket> > BucketMap; BucketMap buckets_; + + typedef Error (CommonDecoder::*CmdHandler)( + uint32 immediate_data_size, + const void* data); + + // A struct to hold info about each command. + struct CommandInfo { + CmdHandler cmd_handler; + uint8 arg_flags; // How to handle the arguments for this command + uint8 cmd_flags; // How to handle this command + uint16 arg_count; // How many arguments are expected for this command. + }; + + // A table of CommandInfo for all the commands. + static const CommandInfo command_info[]; + }; } // namespace gpu
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 5fb0fa8..13b10c5 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -1170,6 +1170,10 @@ GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset, const std::string& name_str); + error::Error GetFragDataLocationHelper( + GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset, + const std::string& name_str); + // Wrapper for glShaderSource. void DoShaderSource( GLuint client_id, GLsizei count, const char** data, const GLint* length); @@ -8124,6 +8128,47 @@ c.program, c.location_shm_id, c.location_shm_offset, name_str); } +error::Error GLES2DecoderImpl::GetFragDataLocationHelper( + GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset, + const std::string& name_str) { + GLint* location = GetSharedMemoryAs<GLint*>( + location_shm_id, location_shm_offset, sizeof(GLint)); + if (!location) { + return error::kOutOfBounds; + } + // Require the client to init this incase the context is lost and we are no + // longer executing commands. + if (*location != -1) { + return error::kGenericError; + } + Program* program = GetProgramInfoNotShader( + client_id, "glGetFragDataLocation"); + if (!program) { + return error::kNoError; + } + *location = glGetFragDataLocation(program->service_id(), name_str.c_str()); + return error::kNoError; +} + +error::Error GLES2DecoderImpl::HandleGetFragDataLocation( + uint32 immediate_data_size, + const void* cmd_data) { + if (!unsafe_es3_apis_enabled()) + return error::kUnknownCommand; + const gles2::cmds::GetFragDataLocation& c = + *static_cast<const gles2::cmds::GetFragDataLocation*>(cmd_data); + Bucket* bucket = GetBucket(c.name_bucket_id); + if (!bucket) { + return error::kInvalidArguments; + } + std::string name_str; + if (!bucket->GetAsString(&name_str)) { + return error::kInvalidArguments; + } + return GetFragDataLocationHelper( + c.program, c.location_shm_id, c.location_shm_offset, name_str); +} + error::Error GLES2DecoderImpl::HandleGetString(uint32 immediate_data_size, const void* cmd_data) { const gles2::cmds::GetString& c =
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h index 0a78a60..18a61052 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h
@@ -876,7 +876,8 @@ TEST_P(GLES2DecoderTest1, FenceSyncValidArgs) { const GLsync kNewServiceIdGLuint = reinterpret_cast<GLsync>(kNewServiceId); - EXPECT_CALL(*gl_, FenceSync(0x9117, 0)).WillOnce(Return(kNewServiceIdGLuint)); + EXPECT_CALL(*gl_, FenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0)) + .WillOnce(Return(kNewServiceIdGLuint)); SpecializedSetup<cmds::FenceSync, 0>(true); cmds::FenceSync cmd; cmd.Init(kNewClientId); @@ -1394,6 +1395,7 @@ EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); EXPECT_EQ(0u, result->size); } +// TODO(gman): GetFragDataLocation TEST_P(GLES2DecoderTest1, GetFramebufferAttachmentParameterivValidArgs) { EXPECT_CALL(*gl_, GetError()) @@ -1943,6 +1945,4 @@ // TODO(gman): GetUniformiv -// TODO(gman): GetUniformLocation - #endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_1_AUTOGEN_H_
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h index 8670cbc3..a5831d6c 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h
@@ -12,6 +12,8 @@ #ifndef GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_2_AUTOGEN_H_ #define GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_2_AUTOGEN_H_ +// TODO(gman): GetUniformLocation + TEST_P(GLES2DecoderTest2, GetVertexAttribfvValidArgs) { SpecializedSetup<cmds::GetVertexAttribfv, 0>(true); typedef cmds::GetVertexAttribfv::Result Result; @@ -540,7 +542,70 @@ } // TODO(gman): ShaderBinary -// TODO(gman): ShaderSourceBucket +TEST_P(GLES2DecoderTest2, ShaderSourceBucketValidArgs) { + const uint32 kBucketId = 123; + const char kSource0[] = "hello"; + const char* kSource[] = {kSource0}; + const char kValidStrEnd = 0; + SetBucketAsCStrings(kBucketId, 1, kSource, 1, kValidStrEnd); + cmds::ShaderSourceBucket cmd; + cmd.Init(client_shader_id_, kBucketId); + decoder_->set_unsafe_es3_apis_enabled(true); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); +} + +TEST_P(GLES2DecoderTest2, ShaderSourceBucketInvalidArgs) { + const uint32 kBucketId = 123; + const char kSource0[] = "hello"; + const char* kSource[] = {kSource0}; + const char kValidStrEnd = 0; + decoder_->set_unsafe_es3_apis_enabled(true); + cmds::ShaderSourceBucket cmd; + // Test no bucket. + cmd.Init(client_shader_id_, kBucketId); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); + // Test invalid client. + SetBucketAsCStrings(kBucketId, 1, kSource, 1, kValidStrEnd); + cmd.Init(kInvalidClientId, kBucketId); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); +} + +TEST_P(GLES2DecoderTest2, ShaderSourceBucketInvalidHeader) { + const uint32 kBucketId = 123; + const char kSource0[] = "hello"; + const char* kSource[] = {kSource0}; + const char kValidStrEnd = 0; + const GLsizei kCount = static_cast<GLsizei>(arraysize(kSource)); + const GLsizei kTests[] = { + kCount, 0, std::numeric_limits<GLsizei>::max(), -1, kCount, + }; + decoder_->set_unsafe_es3_apis_enabled(true); + for (size_t ii = 0; ii < arraysize(kTests); ++ii) { + SetBucketAsCStrings(kBucketId, 1, kSource, kTests[ii], kValidStrEnd); + cmds::ShaderSourceBucket cmd; + cmd.Init(client_shader_id_, kBucketId); + if (kTests[ii] == kCount) { + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + } else { + EXPECT_EQ(error::kInvalidArguments, ExecuteCmd(cmd)); + } + } + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderTest2, ShaderSourceBucketInvalidStringEnding) { + const uint32 kBucketId = 123; + const char kSource0[] = "hello"; + const char* kSource[] = {kSource0}; + const char kInvalidStrEnd = '*'; + SetBucketAsCStrings(kBucketId, 1, kSource, 1, kInvalidStrEnd); + cmds::ShaderSourceBucket cmd; + cmd.Init(client_shader_id_, kBucketId); + decoder_->set_unsafe_es3_apis_enabled(true); + EXPECT_EQ(error::kInvalidArguments, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} TEST_P(GLES2DecoderTest2, StencilFuncValidArgs) { EXPECT_CALL(*gl_, StencilFunc(GL_NEVER, 2, 3)); @@ -1421,6 +1486,4 @@ } // TODO(gman): VertexAttribIPointer -// TODO(gman): VertexAttribPointer - #endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_2_AUTOGEN_H_
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h index bd1163d..20c09f6 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h
@@ -12,6 +12,8 @@ #ifndef GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_3_AUTOGEN_H_ #define GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_3_AUTOGEN_H_ +// TODO(gman): VertexAttribPointer + TEST_P(GLES2DecoderTest3, ViewportValidArgs) { EXPECT_CALL(*gl_, Viewport(1, 2, 3, 4)); SpecializedSetup<cmds::Viewport, 0>(true);
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_programs.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_programs.cc index fefaacf3..bcfeb1b 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_programs.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_programs.cc
@@ -711,28 +711,19 @@ kSource0, bucket->size())); } -TEST_P(GLES2DecoderTest, ShaderSourceBucketInvalidArgs) { +#if GLES2_TEST_SHADER_VS_PROGRAM_IDS +TEST_P(GLES2DecoderTest, ShaderSourceBucketWithProgramId) { const uint32 kBucketId = 123; const char kSource0[] = "hello"; const char* kSource[] = { kSource0 }; const char kValidStrEnd = 0; - ShaderSourceBucket cmd; - // Test no bucket. - cmd.Init(client_shader_id_, kBucketId); - EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); - // Test invalid client. SetBucketAsCStrings(kBucketId, 1, kSource, 1, kValidStrEnd); - cmd.Init(kInvalidClientId, kBucketId); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); -#if GLES2_TEST_SHADER_VS_PROGRAM_IDS - SetBucketAsCStrings(kBucketId, 1, kSource); - cmd.Init( - client_program_id_, kBucketId); + ShaderSourceBucket cmd; + cmd.Init(client_program_id_, kBucketId); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); -#endif // GLES2_TEST_SHADER_VS_PROGRAM_IDS } +#endif // GLES2_TEST_SHADER_VS_PROGRAM_IDS TEST_P(GLES2DecoderTest, ShaderSourceStripComments) { const uint32 kInBucketId = 123; @@ -746,45 +737,6 @@ EXPECT_EQ(GL_NO_ERROR, GetGLError()); } -TEST_P(GLES2DecoderTest, ShaderSourceInvalidHeader) { - const uint32 kInBucketId = 123; - const char kSource0[] = "hello"; - const char* kSource[] = { kSource0 }; - const char kValidStrEnd = 0; - const GLsizei kCount = 1; - const GLsizei kTests[] = { - kCount + 1, - 0, - std::numeric_limits<GLsizei>::max(), - -1, - kCount - }; - size_t kTestCount = 5; - for (size_t ii = 0; ii < kTestCount; ++ii) { - SetBucketAsCStrings(kInBucketId, 1, kSource, kTests[ii], kValidStrEnd); - ShaderSourceBucket cmd; - cmd.Init(client_shader_id_, kInBucketId); - if (kTests[ii] == kCount) { - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - } else { - EXPECT_EQ(error::kInvalidArguments, ExecuteCmd(cmd)); - } - } - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_P(GLES2DecoderTest, ShaderSourceInvalidStringEnding) { - const uint32 kInBucketId = 123; - const char kSource0[] = "hello"; - const char* kSource[] = { kSource0 }; - const char kInvalidStrEnd = '*'; - SetBucketAsCStrings(kInBucketId, 1, kSource, 1, kInvalidStrEnd); - ShaderSourceBucket cmd; - cmd.Init(client_shader_id_, kInBucketId); - EXPECT_EQ(error::kInvalidArguments, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - TEST_P(GLES2DecoderWithShaderTest, Uniform1iValidArgs) { EXPECT_CALL(*gl_, Uniform1i(kUniform1RealLocation, 2)); Uniform1i cmd; @@ -923,6 +875,58 @@ EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); } +TEST_P(GLES2DecoderWithShaderTest, GetFragDataLocation) { + const uint32 kBucketId = 123; + const GLint kLocation = 10; + const char* kName = "color"; + typedef GetFragDataLocation::Result Result; + Result* result = GetSharedMemoryAs<Result*>(); + SetBucketAsCString(kBucketId, kName); + *result = -1; + GetFragDataLocation cmd; + cmd.Init(client_program_id_, kBucketId, kSharedMemoryId, kSharedMemoryOffset); + EXPECT_CALL(*gl_, GetFragDataLocation(kServiceProgramId, StrEq(kName))) + .WillOnce(Return(kLocation)) + .RetiresOnSaturation(); + decoder_->set_unsafe_es3_apis_enabled(true); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(kLocation, *result); + decoder_->set_unsafe_es3_apis_enabled(false); + EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd)); +} + +TEST_P(GLES2DecoderWithShaderTest, GetFragDataLocationInvalidArgs) { + const uint32 kBucketId = 123; + typedef GetFragDataLocation::Result Result; + Result* result = GetSharedMemoryAs<Result*>(); + *result = -1; + GetFragDataLocation cmd; + decoder_->set_unsafe_es3_apis_enabled(true); + // Check no bucket + cmd.Init(client_program_id_, kBucketId, kSharedMemoryId, kSharedMemoryOffset); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(-1, *result); + // Check bad program id. + const char* kName = "color"; + SetBucketAsCString(kBucketId, kName); + cmd.Init(kInvalidClientId, kBucketId, kSharedMemoryId, kSharedMemoryOffset); + *result = -1; + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(-1, *result); + EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); + // Check bad memory + cmd.Init(client_program_id_, + kBucketId, + kInvalidSharedMemoryId, + kSharedMemoryOffset); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); + cmd.Init(client_program_id_, + kBucketId, + kSharedMemoryId, + kInvalidSharedMemoryOffset); + EXPECT_NE(error::kNoError, ExecuteCmd(cmd)); +} + TEST_P(GLES2DecoderWithShaderTest, GetUniformLocation) { const uint32 kBucketId = 123; const char* kNonExistentName = "foobar";
diff --git a/gpu/command_buffer/service/gpu_scheduler.cc b/gpu/command_buffer/service/gpu_scheduler.cc index 3f8f1bf..93cf89f0 100644 --- a/gpu/command_buffer/service/gpu_scheduler.cc +++ b/gpu/command_buffer/service/gpu_scheduler.cc
@@ -61,7 +61,7 @@ if (!IsScheduled()) return; - base::TimeTicks begin_time(base::TimeTicks::HighResNow()); + base::TimeTicks begin_time(base::TimeTicks::Now()); error::Error error = error::kNoError; if (decoder_) decoder_->BeginDecoding(); @@ -102,8 +102,7 @@ command_buffer_->SetParseError(error::kLostContext); } decoder_->EndDecoding(); - decoder_->AddProcessingCommandsTime( - base::TimeTicks::HighResNow() - begin_time); + decoder_->AddProcessingCommandsTime(base::TimeTicks::Now() - begin_time); } }
diff --git a/gpu/command_buffer/service/gpu_tracer.cc b/gpu/command_buffer/service/gpu_tracer.cc index 364159b..84656c3 100644 --- a/gpu/command_buffer/service/gpu_tracer.cc +++ b/gpu/command_buffer/service/gpu_tracer.cc
@@ -11,6 +11,8 @@ #include "base/strings/string_util.h" #include "base/time/time.h" #include "gpu/command_buffer/common/gles2_cmd_utils.h" +#include "gpu/command_buffer/service/context_group.h" +#include "ui/gl/gl_version_info.h" namespace gpu { namespace gles2 { @@ -137,12 +139,10 @@ case kTracerTypeDisjointTimer: // For the disjoint timer, GPU idle time does not seem to increment the - // internal counter. We must calculate the offset before any query. The - // good news is any device that supports disjoint timer will also support - // glGetInteger64v, so we can query it directly unlike the ARBTimer case. - // The "offset_" variable will always be 0 during normal use cases, only - // under the unit tests will it be set to specific test values. - if (offset_ == 0) { + // internal counter. We must calculate the offset before any query. + // glGetInteger64v is supported under ES3 which we check for before using + // the kTracerTypeDisjointTimer. + { GLint64 gl_now = 0; glGetInteger64v(GL_TIMESTAMP, &gl_now); offset_ = cpu_time_->GetCurrentTime() - @@ -180,7 +180,7 @@ return false; GLint done = 0; - glGetQueryObjectiv(queries_[1], GL_QUERY_RESULT_AVAILABLE, &done); + glGetQueryObjectivARB(queries_[1], GL_QUERY_RESULT_AVAILABLE, &done); return !!done; } @@ -385,7 +385,12 @@ } GpuTracerType GPUTracer::DetermineTracerType() { - if (gfx::g_driver_gl.ext.b_GL_EXT_disjoint_timer_query) { + ContextGroup* context_group = decoder_->GetContextGroup(); + const gpu::gles2::FeatureInfo* feature_info = context_group->feature_info(); + const gfx::GLVersionInfo& version_info = feature_info->gl_version_info(); + + if (version_info.is_es3 && + gfx::g_driver_gl.ext.b_GL_EXT_disjoint_timer_query) { return kTracerTypeDisjointTimer; } else if (gfx::g_driver_gl.ext.b_GL_ARB_timer_query) { return kTracerTypeARBTimer; @@ -446,35 +451,16 @@ if (*gpu_trace_dev_category == '\0') { // If GPU device category is off, invalidate timing sync. gpu_timing_synced_ = false; - return; - } else if (tracer_type_ == kTracerTypeDisjointTimer) { - // Disjoint timers offsets should be calculated before every query. + } else if (!gpu_timing_synced_ && tracer_type_ == kTracerTypeARBTimer) { + TRACE_EVENT0("gpu", "GPUTracer::CalculateTimerOffset"); + + // ARB Timer is written for OpenGL 3.2 which contains glGetInteger64v(). + GLint64 gl_now = 0; + glGetInteger64v(GL_TIMESTAMP, &gl_now); + timer_offset_ = cpu_time_->GetCurrentTime() - + gl_now / base::Time::kNanosecondsPerMicrosecond; gpu_timing_synced_ = true; - timer_offset_ = 0; } - - if (gpu_timing_synced_) - return; - - TRACE_EVENT0("gpu", "GPUTracer::CalculateTimerOffset"); - - // NOTE(vmiura): It would be better to use glGetInteger64v, however - // it's not available everywhere. - GLuint64 gl_now = 0; - GLuint query; - - glGenQueriesARB(1, &query); - - glFinish(); - glQueryCounter(query, GL_TIMESTAMP); - glFinish(); - - glGetQueryObjectui64v(query, GL_QUERY_RESULT, &gl_now); - glDeleteQueriesARB(1, &query); - - gl_now /= base::Time::kNanosecondsPerMicrosecond; - timer_offset_ = cpu_time_->GetCurrentTime() - gl_now; - gpu_timing_synced_ = true; } }
diff --git a/gpu/command_buffer/service/gpu_tracer_unittest.cc b/gpu/command_buffer/service/gpu_tracer_unittest.cc index 1b55e78..3737018 100644 --- a/gpu/command_buffer/service/gpu_tracer_unittest.cc +++ b/gpu/command_buffer/service/gpu_tracer_unittest.cc
@@ -88,7 +88,7 @@ } } - void GetQueryObjectiv(GLuint id, GLenum pname, GLint* params) { + void GetQueryObjectivARB(GLuint id, GLenum pname, GLint* params) { switch (pname) { case GL_QUERY_RESULT_AVAILABLE: { std::map<GLuint, GLint64>::iterator it = query_timestamp_.find(id); @@ -99,7 +99,7 @@ break; } default: - FAIL() << "Invalid variable passed to GetQueryObjectiv: " << pname; + FAIL() << "Invalid variable passed to GetQueryObjectivARB: " << pname; } } @@ -255,10 +255,10 @@ .WillRepeatedly( Invoke(&gl_fake_queries_, &GlFakeQueries::GenQueriesARB)); - EXPECT_CALL(*gl_, GetQueryObjectiv(_, GL_QUERY_RESULT_AVAILABLE, + EXPECT_CALL(*gl_, GetQueryObjectivARB(_, GL_QUERY_RESULT_AVAILABLE, NotNull())) .WillRepeatedly( - Invoke(&gl_fake_queries_, &GlFakeQueries::GetQueryObjectiv)); + Invoke(&gl_fake_queries_, &GlFakeQueries::GetQueryObjectivARB)); if (GetTracerType() == kTracerTypeDisjointTimer) { EXPECT_CALL(*gl_, GetInteger64v(GL_TIMESTAMP, _)) @@ -330,36 +330,13 @@ // Timer offset calculation should only happen for the regular timer. if (GetTracerType() != kTracerTypeARBTimer) { - EXPECT_CALL(*gl_, GenQueriesARB(_, NotNull())).Times(Exactly(0)); - EXPECT_CALL(*gl_, Finish()).Times(Exactly(0)); - EXPECT_CALL(*gl_, QueryCounter(_, GL_TIMESTAMP)).Times(Exactly(0)); - EXPECT_CALL(*gl_, GetQueryObjectui64v(_, GL_QUERY_RESULT, NotNull())) + EXPECT_CALL(*gl_, GetInteger64v(GL_TIMESTAMP, NotNull())) .Times(Exactly(0)); - EXPECT_CALL(*gl_, DeleteQueriesARB(_, NotNull())).Times(Exactly(0)); } else { - EXPECT_CALL(*gl_, GenQueriesARB(_, NotNull())).Times(AtLeast(1)) - .WillRepeatedly( - Invoke(&gl_fake_queries_, &GlFakeQueries::GenQueriesARB)); - - EXPECT_CALL(*gl_, Finish()).Times(AtLeast(2)) - .WillRepeatedly( - Invoke(&gl_fake_queries_, &GlFakeQueries::Finish)); - - EXPECT_CALL(*gl_, QueryCounter(_, GL_TIMESTAMP)) + EXPECT_CALL(*gl_, GetInteger64v(GL_TIMESTAMP, NotNull())) .Times(AtLeast(1)) .WillRepeatedly( - Invoke(&gl_fake_queries_, &GlFakeQueries::QueryCounter)); - - EXPECT_CALL(*gl_, GetQueryObjectui64v(_, GL_QUERY_RESULT, NotNull())) - .Times(AtLeast(1)) - .WillRepeatedly( - Invoke(&gl_fake_queries_, - &GlFakeQueries::GetQueryObjectui64v)); - - EXPECT_CALL(*gl_, DeleteQueriesARB(1, NotNull())) - .Times(AtLeast(1)) - .WillRepeatedly( - Invoke(&gl_fake_queries_, &GlFakeQueries::DeleteQueriesARB)); + Invoke(&gl_fake_queries_, &GlFakeQueries::GetInteger64v)); } } @@ -404,6 +381,7 @@ offset_time, GetTracerType()); gl_fake_queries_.SetCurrentGLTime(start_timestamp); + cpu_time_ref_->SetFakeCPUTime(expect_start_time); trace->Start(true); // Shouldn't be available before End() call
diff --git a/gpu/command_buffer/service/in_process_command_buffer.cc b/gpu/command_buffer/service/in_process_command_buffer.cc index c671073..7a6556b 100644 --- a/gpu/command_buffer/service/in_process_command_buffer.cc +++ b/gpu/command_buffer/service/in_process_command_buffer.cc
@@ -101,8 +101,9 @@ } void GpuInProcessThread::ScheduleIdleWork(const base::Closure& callback) { + // Match delay with GpuCommandBufferStub. message_loop()->PostDelayedTask( - FROM_HERE, callback, base::TimeDelta::FromMilliseconds(5)); + FROM_HERE, callback, base::TimeDelta::FromMilliseconds(2)); } scoped_refptr<gles2::ShaderTranslatorCache> @@ -238,6 +239,13 @@ InProcessCommandBuffer::Service::~Service() {} +scoped_refptr<gfx::GLShareGroup> +InProcessCommandBuffer::Service::share_group() { + if (!share_group_.get()) + share_group_ = new gfx::GLShareGroup; + return share_group_; +} + scoped_refptr<gles2::MailboxManager> InProcessCommandBuffer::Service::mailbox_manager() { if (!mailbox_manager_.get()) { @@ -397,8 +405,8 @@ } gl_share_group_ = params.context_group - ? params.context_group->gl_share_group_.get() - : new gfx::GLShareGroup; + ? params.context_group->gl_share_group_ + : service_->share_group(); #if defined(OS_ANDROID) stream_texture_manager_.reset(new StreamTextureManagerInProcess);
diff --git a/gpu/command_buffer/service/in_process_command_buffer.h b/gpu/command_buffer/service/in_process_command_buffer.h index eec889f..ab68f152 100644 --- a/gpu/command_buffer/service/in_process_command_buffer.h +++ b/gpu/command_buffer/service/in_process_command_buffer.h
@@ -139,11 +139,13 @@ virtual bool UseVirtualizedGLContexts() = 0; virtual scoped_refptr<gles2::ShaderTranslatorCache> shader_translator_cache() = 0; + scoped_refptr<gfx::GLShareGroup> share_group(); scoped_refptr<gles2::MailboxManager> mailbox_manager(); scoped_refptr<gles2::SubscriptionRefSet> subscription_ref_set(); scoped_refptr<gpu::ValueStateMap> pending_valuebuffer_state(); private: + scoped_refptr<gfx::GLShareGroup> share_group_; scoped_refptr<gles2::MailboxManager> mailbox_manager_; scoped_refptr<gles2::SubscriptionRefSet> subscription_ref_set_; scoped_refptr<gpu::ValueStateMap> pending_valuebuffer_state_;
diff --git a/gpu/command_buffer/service/program_manager.cc b/gpu/command_buffer/service/program_manager.cc index 634fbc0..d7763508 100644 --- a/gpu/command_buffer/service/program_manager.cc +++ b/gpu/command_buffer/service/program_manager.cc
@@ -553,7 +553,7 @@ return false; } - TimeTicks before_time = TimeTicks::HighResNow(); + TimeTicks before_time = TimeTicks::Now(); bool link = true; ProgramCache* cache = manager_->program_cache_; if (cache) { @@ -582,7 +582,7 @@ if (link) { ExecuteBindAttribLocationCalls(); - before_time = TimeTicks::HighResNow(); + before_time = TimeTicks::Now(); if (cache && gfx::g_driver_gl.ext.b_GL_ARB_get_program_binary) { glProgramParameteri(service_id(), PROGRAM_BINARY_RETRIEVABLE_HINT, @@ -608,7 +608,7 @@ UMA_HISTOGRAM_CUSTOM_COUNTS( "GPU.ProgramCache.BinaryCacheMissTime", static_cast<base::HistogramBase::Sample>( - (TimeTicks::HighResNow() - before_time).InMicroseconds()), + (TimeTicks::Now() - before_time).InMicroseconds()), 0, static_cast<base::HistogramBase::Sample>( TimeDelta::FromSeconds(10).InMicroseconds()), @@ -617,7 +617,7 @@ UMA_HISTOGRAM_CUSTOM_COUNTS( "GPU.ProgramCache.BinaryCacheHitTime", static_cast<base::HistogramBase::Sample>( - (TimeTicks::HighResNow() - before_time).InMicroseconds()), + (TimeTicks::Now() - before_time).InMicroseconds()), 0, static_cast<base::HistogramBase::Sample>( TimeDelta::FromSeconds(1).InMicroseconds()),
diff --git a/gpu/command_buffer/service/query_manager.cc b/gpu/command_buffer/service/query_manager.cc index 8b753337..c0808c4 100644 --- a/gpu/command_buffer/service/query_manager.cc +++ b/gpu/command_buffer/service/query_manager.cc
@@ -216,12 +216,12 @@ } bool CommandsIssuedQuery::Begin() { - begin_time_ = base::TimeTicks::HighResNow(); + begin_time_ = base::TimeTicks::Now(); return true; } bool CommandsIssuedQuery::End(base::subtle::Atomic32 submit_count) { - base::TimeDelta elapsed = base::TimeTicks::HighResNow() - begin_time_; + base::TimeDelta elapsed = base::TimeTicks::Now() - begin_time_; MarkAsPending(submit_count); return MarkAsCompleted(elapsed.InMicroseconds()); } @@ -264,7 +264,7 @@ } bool CommandLatencyQuery::End(base::subtle::Atomic32 submit_count) { - base::TimeDelta now = base::TimeTicks::HighResNow() - base::TimeTicks(); + base::TimeDelta now = base::TimeTicks::Now() - base::TimeTicks(); MarkAsPending(submit_count); return MarkAsCompleted(now.InMicroseconds()); } @@ -418,7 +418,7 @@ : Query(manager, target, shm_id, shm_offset) {} bool CommandsCompletedQuery::Begin() { - begin_time_ = base::TimeTicks::HighResNow(); + begin_time_ = base::TimeTicks::Now(); return true; } @@ -435,7 +435,7 @@ if (!did_finish && fence_ && !fence_->HasCompleted()) return true; - base::TimeDelta elapsed = base::TimeTicks::HighResNow() - begin_time_; + base::TimeDelta elapsed = base::TimeTicks::Now() - begin_time_; return MarkAsCompleted(elapsed.InMicroseconds()); }
diff --git a/gpu/command_buffer/service/texture_manager.cc b/gpu/command_buffer/service/texture_manager.cc index b914f6dde..b066e8d1 100644 --- a/gpu/command_buffer/service/texture_manager.cc +++ b/gpu/command_buffer/service/texture_manager.cc
@@ -1718,13 +1718,13 @@ ScopedTextureUploadTimer::ScopedTextureUploadTimer( DecoderTextureState* texture_state) : texture_state_(texture_state), - begin_time_(base::TimeTicks::HighResNow()) { + begin_time_(base::TimeTicks::Now()) { } ScopedTextureUploadTimer::~ScopedTextureUploadTimer() { texture_state_->texture_upload_count++; texture_state_->total_texture_upload_time += - base::TimeTicks::HighResNow() - begin_time_; + base::TimeTicks::Now() - begin_time_; } } // namespace gles2
diff --git a/gpu/command_buffer/tests/gl_query_unittest.cc b/gpu/command_buffer/tests/gl_query_unittest.cc index 5ea7e8d..b12adc3 100644 --- a/gpu/command_buffer/tests/gl_query_unittest.cc +++ b/gpu/command_buffer/tests/gl_query_unittest.cc
@@ -36,7 +36,7 @@ GLuint available; GLuint result; - base::TimeTicks before = base::TimeTicks::HighResNow(); + base::TimeTicks before = base::TimeTicks::Now(); // Begin two queries of different types glBeginQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM, commands_issue_query); @@ -50,7 +50,7 @@ glFinish(); - base::TimeTicks after = base::TimeTicks::HighResNow(); + base::TimeTicks after = base::TimeTicks::Now(); // Check that we got result on both queries. @@ -152,7 +152,7 @@ return; } - base::TimeTicks before = base::TimeTicks::HighResNow(); + base::TimeTicks before = base::TimeTicks::Now(); GLuint query; glGenQueriesEXT(1, &query); @@ -164,7 +164,7 @@ GLuint result = 0; glGetQueryObjectuivEXT(query, GL_QUERY_RESULT_EXT, &result); - base::TimeTicks after = base::TimeTicks::HighResNow(); + base::TimeTicks after = base::TimeTicks::Now(); // Sanity check - the resulting delta is shorter than the time it took to // run this test. EXPECT_LE(result, base::TimeDelta(after - before).InMicroseconds()); @@ -194,5 +194,3 @@ } } // namespace gpu - -
diff --git a/gpu/config/gpu_driver_bug_list_json.cc b/gpu/config/gpu_driver_bug_list_json.cc index 4c817eea..26be952 100644 --- a/gpu/config/gpu_driver_bug_list_json.cc +++ b/gpu/config/gpu_driver_bug_list_json.cc
@@ -19,7 +19,7 @@ { "name": "gpu driver bug list", // Please update the version number whenever you change this file. - "version": "7.13", + "version": "7.14", "entries": [ { "id": 1, @@ -1052,7 +1052,7 @@ "type": "android", "version": { "op": "<=", - "value": "5.0.1" + "value": "5.0.2" } }, "gl_vendor": "NVIDIA.*", @@ -1105,6 +1105,19 @@ "features": [ "disable_multisampling" ] + }, + { + "id": 98, + "description": "PowerVR SGX 540 drivers throw GL_OUT_OF_MEMORY error when a buffer object's size is set to 0", + "cr_bugs": [451501], + "os": { + "type": "android" + }, + "gl_vendor": "Imagination.*", + "gl_renderer": "PowerVR SGX 540", + "features": [ + "use_non_zero_size_for_client_side_stream_buffers" + ] } ] }
diff --git a/ios/chrome/browser/web_resource/ios_web_resource_service.cc b/ios/chrome/browser/web_resource/ios_web_resource_service.cc new file mode 100644 index 0000000..5d538c9 --- /dev/null +++ b/ios/chrome/browser/web_resource/ios_web_resource_service.cc
@@ -0,0 +1,81 @@ +// Copyright 2015 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 "ios/chrome/browser/web_resource/ios_web_resource_service.h" + +#include "base/bind.h" +#include "base/json/json_reader.h" +#include "base/values.h" +#include "ios/chrome/browser/application_context.h" +#include "ios/web/public/web_thread.h" + +namespace { + +const char kInvalidDataTypeError[] = + "Data from web resource server is missing or not valid JSON."; + +const char kUnexpectedJSONFormatError[] = + "Data from web resource server does not have expected format."; + +// Helper method to run a closure. +void RunClosure(const base::Closure& closure) { + closure.Run(); +} + +} // namespace + +IOSWebResourceService::IOSWebResourceService( + PrefService* prefs, + const GURL& web_resource_server, + bool apply_locale_to_url, + const char* last_update_time_pref_name, + int start_fetch_delay_ms, + int cache_update_delay_ms) + : web_resource::WebResourceService( + prefs, + web_resource_server, + apply_locale_to_url ? GetApplicationContext()->GetApplicationLocale() + : std::string(), + last_update_time_pref_name, + start_fetch_delay_ms, + cache_update_delay_ms, + nullptr) { +} + +IOSWebResourceService::~IOSWebResourceService() { +} + +// static +base::Closure IOSWebResourceService::ParseJSONOnBackgroundThread( + const std::string& data, + const SuccessCallback& success_callback, + const ErrorCallback& error_callback) { + if (data.empty()) + return base::Bind(error_callback, std::string(kInvalidDataTypeError)); + + scoped_ptr<base::Value> value(base::JSONReader::Read(data)); + if (!value.get()) { + // Page information not properly read, or corrupted. + return base::Bind(error_callback, std::string(kInvalidDataTypeError)); + } + + if (!value->IsType(base::Value::TYPE_DICTIONARY)) + return base::Bind(error_callback, std::string(kUnexpectedJSONFormatError)); + + return base::Bind(success_callback, base::Passed(&value)); +} + +void IOSWebResourceService::ParseJSON(const std::string& data, + const SuccessCallback& success_callback, + const ErrorCallback& error_callback) { + base::PostTaskAndReplyWithResult( + web::WebThread::GetBlockingPool(), FROM_HERE, + base::Bind(&IOSWebResourceService::ParseJSONOnBackgroundThread, data, + success_callback, error_callback), + base::Bind(&RunClosure)); +} + +net::URLRequestContextGetter* IOSWebResourceService::GetRequestContext() { + return GetApplicationContext()->GetSystemURLRequestContext(); +}
diff --git a/ios/chrome/browser/web_resource/ios_web_resource_service.h b/ios/chrome/browser/web_resource/ios_web_resource_service.h new file mode 100644 index 0000000..c64de5d --- /dev/null +++ b/ios/chrome/browser/web_resource/ios_web_resource_service.h
@@ -0,0 +1,45 @@ +// Copyright 2015 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 IOS_CHROME_BROWSER_WEB_RESOURCE_IOS_WEB_RESOURCE_SERVICE_H_ +#define IOS_CHROME_BROWSER_WEB_RESOURCE_IOS_WEB_RESOURCE_SERVICE_H_ + +#include <string> + +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "components/web_resource/web_resource_service.h" + +// iOS implementation of WebResourceService. +// IOSWebResourceService does not parses JSON out of process, because of +// platform limitations. +class IOSWebResourceService : public web_resource::WebResourceService { + public: + IOSWebResourceService(PrefService* prefs, + const GURL& web_resource_server, + bool apply_locale_to_url, + const char* last_update_time_pref_name, + int start_fetch_delay_ms, + int cache_update_delay_ms); + + protected: + ~IOSWebResourceService() override; + + private: + // Parses JSON in a background thread. + static base::Closure ParseJSONOnBackgroundThread( + const std::string& data, + const SuccessCallback& success_callback, + const ErrorCallback& error_callback); + + // WebResourceService implementation: + void ParseJSON(const std::string& data, + const SuccessCallback& success_callback, + const ErrorCallback& error_callback) override; + net::URLRequestContextGetter* GetRequestContext() override; + + DISALLOW_COPY_AND_ASSIGN(IOSWebResourceService); +}; + +#endif // IOS_CHROME_BROWSER_WEB_RESOURCE_IOS_WEB_RESOURCE_SERVICE_H_
diff --git a/ios/chrome/ios_chrome.gyp b/ios/chrome/ios_chrome.gyp index 2f94b0d..76cb0c8d 100644 --- a/ios/chrome/ios_chrome.gyp +++ b/ios/chrome/ios_chrome.gyp
@@ -99,6 +99,8 @@ 'browser/ui/ui_util.mm', 'browser/ui/uikit_ui_util.h', 'browser/ui/uikit_ui_util.mm', + 'browser/web_resource/ios_web_resource_service.cc', + 'browser/web_resource/ios_web_resource_service.h', ], }, ],
diff --git a/ipc/BUILD.gn b/ipc/BUILD.gn index ac5631f..a440593 100644 --- a/ipc/BUILD.gn +++ b/ipc/BUILD.gn
@@ -31,6 +31,8 @@ "ipc_logging.h", "ipc_message.cc", "ipc_message.h", + "ipc_message_attachment.cc", + "ipc_message_attachment.h", "ipc_message_attachment_set.cc", "ipc_message_attachment_set.h", "ipc_message_macros.h", @@ -40,6 +42,8 @@ "ipc_param_traits.h", "ipc_platform_file.cc", "ipc_platform_file.h", + "ipc_platform_file_attachment.cc", + "ipc_platform_file_attachment.h", "ipc_sender.h", "ipc_switches.cc", "ipc_switches.h",
diff --git a/ipc/ipc.gypi b/ipc/ipc.gypi index 05dab8c..5e890c6 100644 --- a/ipc/ipc.gypi +++ b/ipc/ipc.gypi
@@ -36,6 +36,8 @@ 'ipc_logging.h', 'ipc_message.cc', 'ipc_message.h', + 'ipc_message_attachment.cc', + 'ipc_message_attachment.h', 'ipc_message_attachment_set.cc', 'ipc_message_attachment_set.h', 'ipc_message_macros.h', @@ -45,6 +47,8 @@ 'ipc_param_traits.h', 'ipc_platform_file.cc', 'ipc_platform_file.h', + 'ipc_platform_file_attachment.cc', + 'ipc_platform_file_attachment.h', 'ipc_sender.h', 'ipc_switches.cc', 'ipc_switches.h',
diff --git a/ipc/ipc_message_attachment.cc b/ipc/ipc_message_attachment.cc new file mode 100644 index 0000000..e6e27a9 --- /dev/null +++ b/ipc/ipc_message_attachment.cc
@@ -0,0 +1,12 @@ +// Copyright (c) 2015 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 "ipc/ipc_message_attachment.h" + +namespace IPC { + +MessageAttachment::~MessageAttachment() { +} + +} // namespace IPC
diff --git a/ipc/ipc_message_attachment.h b/ipc/ipc_message_attachment.h new file mode 100644 index 0000000..09314c2 --- /dev/null +++ b/ipc/ipc_message_attachment.h
@@ -0,0 +1,32 @@ +// Copyright (c) 2015 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 IPC_IPC_MESSAGE_ATTACHMENT_H_ +#define IPC_IPC_MESSAGE_ATTACHMENT_H_ + +#include "base/memory/ref_counted.h" +#include "ipc/ipc_export.h" + +namespace IPC { + +// Auxiliary data sent with |Message|. This can be a platform file descriptor +// or a mojo |MessagePipe|. |GetType()| returns the type of the subclass. +class IPC_EXPORT MessageAttachment + : public base::RefCounted<MessageAttachment> { + public: + enum Type { + TYPE_PLATFORM_FILE, // The instance is |PlatformFileAttachment|. + TYPE_MOJO_MESSAGE_PIPE, // The instance is a mojo-based class. + }; + + virtual Type GetType() const = 0; + + protected: + friend class base::RefCounted<MessageAttachment>; + virtual ~MessageAttachment(); +}; + +} // namespace IPC + +#endif // IPC_IPC_MESSAGE_ATTACHMENT_H_
diff --git a/ipc/ipc_message_attachment_set.cc b/ipc/ipc_message_attachment_set.cc index 665f939..4e27ad2e 100644 --- a/ipc/ipc_message_attachment_set.cc +++ b/ipc/ipc_message_attachment_set.cc
@@ -4,8 +4,11 @@ #include "ipc/ipc_message_attachment_set.h" +#include <algorithm> #include "base/logging.h" #include "base/posix/eintr_wrapper.h" +#include "ipc/ipc_message_attachment.h" +#include "ipc/ipc_platform_file_attachment.h" #if defined(OS_POSIX) #include <sys/types.h> @@ -35,46 +38,27 @@ << consumed_descriptor_highwater_ << "/" << size(); } +unsigned MessageAttachmentSet::num_descriptors() const { + return std::count_if(attachments_.begin(), attachments_.end(), + [](scoped_refptr<MessageAttachment> i) { + return i->GetType() == MessageAttachment::TYPE_PLATFORM_FILE; + }); +} + unsigned MessageAttachmentSet::size() const { -#if defined(OS_POSIX) - return descriptors_.size(); -#else - return 0; -#endif + return static_cast<unsigned>(attachments_.size()); } -#if defined(OS_POSIX) - -bool MessageAttachmentSet::AddToBorrow(base::PlatformFile fd) { - DCHECK_EQ(consumed_descriptor_highwater_, 0u); - - if (size() == kMaxDescriptorsPerMessage) { - DLOG(WARNING) << "Cannot add file descriptor. MessageAttachmentSet full."; - return false; - } - - descriptors_.push_back(fd); - return true; +void MessageAttachmentSet::AddAttachment( + scoped_refptr<MessageAttachment> attachment) { + attachments_.push_back(attachment); } -bool MessageAttachmentSet::AddToOwn(base::ScopedFD fd) { - DCHECK_EQ(consumed_descriptor_highwater_, 0u); - - if (size() == kMaxDescriptorsPerMessage) { - DLOG(WARNING) << "Cannot add file descriptor. MessageAttachmentSet full."; - return false; - } - - descriptors_.push_back(fd.get()); - owned_descriptors_.push_back(new base::ScopedFD(fd.Pass())); - DCHECK(size() <= kMaxDescriptorsPerMessage); - return true; -} - -base::PlatformFile MessageAttachmentSet::TakeDescriptorAt(unsigned index) { +scoped_refptr<MessageAttachment> MessageAttachmentSet::GetAttachmentAt( + unsigned index) { if (index >= size()) { DLOG(WARNING) << "Accessing out of bound index:" << index << "/" << size(); - return -1; + return scoped_refptr<MessageAttachment>(); } // We should always walk the descriptors in order, so it's reasonable to @@ -98,17 +82,53 @@ // end of the array and index 0 is requested, we reset the highwater value. // TODO(morrita): This is absurd. This "wringle" disallow to introduce clearer // ownership model. Only client is NaclIPCAdapter. See crbug.com/415294 - if (index == 0 && consumed_descriptor_highwater_ == descriptors_.size()) + if (index == 0 && consumed_descriptor_highwater_ == size()) consumed_descriptor_highwater_ = 0; if (index != consumed_descriptor_highwater_) - return -1; + return scoped_refptr<MessageAttachment>(); consumed_descriptor_highwater_ = index + 1; - base::PlatformFile file = descriptors_[index]; + return attachments_[index]; +} - // TODO(morrita): In production, descriptors_.size() should be same as +#if defined(OS_POSIX) + +bool MessageAttachmentSet::AddToBorrow(base::PlatformFile fd) { + DCHECK_EQ(consumed_descriptor_highwater_, 0u); + + if (num_descriptors() == kMaxDescriptorsPerMessage) { + DLOG(WARNING) << "Cannot add file descriptor. MessageAttachmentSet full."; + return false; + } + + AddAttachment(new internal::PlatformFileAttachment(fd)); + return true; +} + +bool MessageAttachmentSet::AddToOwn(base::ScopedFD fd) { + DCHECK_EQ(consumed_descriptor_highwater_, 0u); + + if (num_descriptors() == kMaxDescriptorsPerMessage) { + DLOG(WARNING) << "Cannot add file descriptor. MessageAttachmentSet full."; + return false; + } + + AddAttachment(new internal::PlatformFileAttachment(fd.get())); + owned_descriptors_.push_back(new base::ScopedFD(fd.Pass())); + DCHECK(num_descriptors() <= kMaxDescriptorsPerMessage); + return true; +} + +base::PlatformFile MessageAttachmentSet::TakeDescriptorAt(unsigned index) { + scoped_refptr<MessageAttachment> attachment = GetAttachmentAt(index); + if (!attachment) + return -1; + + base::PlatformFile file = internal::GetPlatformFile(attachment); + + // TODO(morrita): In production, attachments_.size() should be same as // owned_descriptors_.size() as all read descriptors are owned by Message. // We have to do this because unit test breaks this assumption. It should be // changed to exercise with own-able descriptors. @@ -125,15 +145,15 @@ } void MessageAttachmentSet::PeekDescriptors(base::PlatformFile* buffer) const { - std::copy(descriptors_.begin(), descriptors_.end(), buffer); + for (size_t i = 0; i != attachments_.size(); ++i) + buffer[i] = internal::GetPlatformFile(attachments_[i]); } bool MessageAttachmentSet::ContainsDirectoryDescriptor() const { struct stat st; - for (std::vector<base::PlatformFile>::const_iterator i = descriptors_.begin(); - i != descriptors_.end(); ++i) { - if (fstat(*i, &st) == 0 && S_ISDIR(st.st_mode)) + for (auto i = attachments_.begin(); i != attachments_.end(); ++i) { + if (fstat(internal::GetPlatformFile(*i), &st) == 0 && S_ISDIR(st.st_mode)) return true; } @@ -141,7 +161,7 @@ } void MessageAttachmentSet::CommitAll() { - descriptors_.clear(); + attachments_.clear(); owned_descriptors_.clear(); consumed_descriptor_highwater_ = 0; } @@ -159,13 +179,13 @@ void MessageAttachmentSet::AddDescriptorsToOwn(const base::PlatformFile* buffer, unsigned count) { DCHECK(count <= kMaxDescriptorsPerMessage); - DCHECK_EQ(size(), 0u); + DCHECK_EQ(num_descriptors(), 0u); DCHECK_EQ(consumed_descriptor_highwater_, 0u); - descriptors_.reserve(count); + attachments_.reserve(count); owned_descriptors_.reserve(count); for (unsigned i = 0; i < count; ++i) { - descriptors_.push_back(buffer[i]); + AddAttachment(new internal::PlatformFileAttachment(buffer[i])); owned_descriptors_.push_back(new base::ScopedFD(buffer[i])); } }
diff --git a/ipc/ipc_message_attachment_set.h b/ipc/ipc_message_attachment_set.h index a257dd0..a143570 100644 --- a/ipc/ipc_message_attachment_set.h +++ b/ipc/ipc_message_attachment_set.h
@@ -18,6 +18,8 @@ namespace IPC { +class MessageAttachment; + // ----------------------------------------------------------------------------- // A MessageAttachmentSet is an ordered set of POSIX file descriptors. These are // associated with IPC messages so that descriptors can be transmitted over a @@ -28,11 +30,16 @@ public: MessageAttachmentSet(); - // Return the number of descriptors + // Return the number of attachments unsigned size() const; + // Return the number of file descriptors + unsigned num_descriptors() const; // Return true if no unconsumed descriptors remain bool empty() const { return 0 == size(); } + void AddAttachment(scoped_refptr<MessageAttachment> attachment); + scoped_refptr<MessageAttachment> GetAttachmentAt(unsigned index); + #if defined(OS_POSIX) // This is the maximum number of descriptors per message. We need to know this // because the control message kernel interface has to be given a buffer which @@ -105,12 +112,15 @@ ~MessageAttachmentSet(); + // A vector of attachments of the message, which might be |PlatformFile| or + // |MessagePipe|. + std::vector<scoped_refptr<MessageAttachment>> attachments_; + #if defined(OS_POSIX) - // A vector of descriptors and close flags. If this message is sent, then - // these descriptors are sent as control data. After sending, any descriptors - // with a true flag are closed. If this message has been received, then these - // are the descriptors which were received and all close flags are true. - std::vector<base::PlatformFile> descriptors_; + // A vector of owning descriptors. If this message is sent, then file + // descriptors are sent as control data. After sending, any owning descriptors + // are closed. If this message has been received then all received + // descriptors are owned by this message. ScopedVector<base::ScopedFD> owned_descriptors_; #endif
diff --git a/ipc/ipc_message_start.h b/ipc/ipc_message_start.h index b22c7b39..48dd9af 100644 --- a/ipc/ipc_message_start.h +++ b/ipc/ipc_message_start.h
@@ -113,6 +113,7 @@ BluetoothMsgStart, NavigatorConnectMsgStart, CastMediaMsgStart, + AwMessagePortMsgStart, LastIPCMsgStart // Must come last. };
diff --git a/ipc/ipc_platform_file_attachment.cc b/ipc/ipc_platform_file_attachment.cc new file mode 100644 index 0000000..5430c6d --- /dev/null +++ b/ipc/ipc_platform_file_attachment.cc
@@ -0,0 +1,28 @@ +// Copyright (c) 2015 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 "ipc/ipc_platform_file_attachment.h" + +namespace IPC { +namespace internal { + +PlatformFileAttachment::PlatformFileAttachment(base::PlatformFile file) + : file_(file) { +} + +PlatformFileAttachment::~PlatformFileAttachment() { +} + +MessageAttachment::Type PlatformFileAttachment::GetType() const { + return TYPE_PLATFORM_FILE; +} + +base::PlatformFile GetPlatformFile( + scoped_refptr<MessageAttachment> attachment) { + DCHECK_EQ(attachment->GetType(), MessageAttachment::TYPE_PLATFORM_FILE); + return static_cast<PlatformFileAttachment*>(attachment.get())->file(); +} + +} // namespace internal +} // namespace IPC
diff --git a/ipc/ipc_platform_file_attachment.h b/ipc/ipc_platform_file_attachment.h new file mode 100644 index 0000000..c4c22a3 --- /dev/null +++ b/ipc/ipc_platform_file_attachment.h
@@ -0,0 +1,35 @@ +// Copyright (c) 2015 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 IPC_IPC_PLATFORM_FILE_ATTACHMENT_H_ +#define IPC_IPC_PLATFORM_FILE_ATTACHMENT_H_ + +#include "base/files/file.h" +#include "ipc/ipc_message_attachment.h" + +namespace IPC { +namespace internal { + +// A platform file that is sent over |Channel| as a part of |Message|. +// |PlatformFileAttachment| doesn't own |file_|. The lifecycle of |file_| is +// managed by |MessageAttachmentSet|. +class PlatformFileAttachment : public MessageAttachment { + public: + explicit PlatformFileAttachment(base::PlatformFile file); + + Type GetType() const override; + base::PlatformFile file() const { return file_; } + + private: + ~PlatformFileAttachment() override; + + base::PlatformFile file_; +}; + +base::PlatformFile GetPlatformFile(scoped_refptr<MessageAttachment> attachment); + +} // namespace internal +} // namespace IPC + +#endif // IPC_IPC_PLATFORM_FILE_ATTACHMENT_H_
diff --git a/ipc/mojo/DEPS b/ipc/mojo/DEPS index 039e243..fb36693 100644 --- a/ipc/mojo/DEPS +++ b/ipc/mojo/DEPS
@@ -1,4 +1,4 @@ include_rules = [ - "+mojo/public", - "+mojo/edk/embedder", + "+third_party/mojo/src/mojo/public", + "+third_party/mojo/src/mojo/edk/embedder", ]
diff --git a/ipc/mojo/async_handle_waiter.cc b/ipc/mojo/async_handle_waiter.cc index f19d782..7b199ed 100644 --- a/ipc/mojo/async_handle_waiter.cc +++ b/ipc/mojo/async_handle_waiter.cc
@@ -10,7 +10,7 @@ #include "base/location.h" #include "base/logging.h" #include "base/message_loop/message_loop.h" -#include "mojo/edk/embedder/embedder.h" +#include "third_party/mojo/src/mojo/edk/embedder/embedder.h" namespace IPC { namespace internal {
diff --git a/ipc/mojo/async_handle_waiter.h b/ipc/mojo/async_handle_waiter.h index 16d9c883..55acb3e 100644 --- a/ipc/mojo/async_handle_waiter.h +++ b/ipc/mojo/async_handle_waiter.h
@@ -9,7 +9,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "ipc/ipc_export.h" -#include "mojo/public/c/system/types.h" +#include "third_party/mojo/src/mojo/public/c/system/types.h" namespace IPC { namespace internal {
diff --git a/ipc/mojo/async_handle_waiter_unittest.cc b/ipc/mojo/async_handle_waiter_unittest.cc index dd13d46..fbaf3ca 100644 --- a/ipc/mojo/async_handle_waiter_unittest.cc +++ b/ipc/mojo/async_handle_waiter_unittest.cc
@@ -8,8 +8,8 @@ #include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/threading/thread.h" -#include "mojo/public/cpp/system/message_pipe.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/mojo/src/mojo/public/cpp/system/message_pipe.h" namespace IPC { namespace internal {
diff --git a/ipc/mojo/ipc_channel_mojo.cc b/ipc/mojo/ipc_channel_mojo.cc index 1f3e3c4..201fe57f 100644 --- a/ipc/mojo/ipc_channel_mojo.cc +++ b/ipc/mojo/ipc_channel_mojo.cc
@@ -13,8 +13,8 @@ #include "ipc/ipc_message_macros.h" #include "ipc/mojo/client_channel.mojom.h" #include "ipc/mojo/ipc_mojo_bootstrap.h" -#include "mojo/edk/embedder/embedder.h" -#include "mojo/public/cpp/bindings/error_handler.h" +#include "third_party/mojo/src/mojo/edk/embedder/embedder.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/error_handler.h" namespace IPC {
diff --git a/ipc/mojo/ipc_channel_mojo.h b/ipc/mojo/ipc_channel_mojo.h index 43dd0d015..5062577 100644 --- a/ipc/mojo/ipc_channel_mojo.h +++ b/ipc/mojo/ipc_channel_mojo.h
@@ -15,8 +15,8 @@ #include "ipc/ipc_export.h" #include "ipc/mojo/ipc_message_pipe_reader.h" #include "ipc/mojo/ipc_mojo_bootstrap.h" -#include "mojo/edk/embedder/channel_info_forward.h" -#include "mojo/public/cpp/system/core.h" +#include "third_party/mojo/src/mojo/edk/embedder/channel_info_forward.h" +#include "third_party/mojo/src/mojo/public/cpp/system/core.h" namespace IPC {
diff --git a/ipc/mojo/ipc_message_pipe_reader.h b/ipc/mojo/ipc_message_pipe_reader.h index 90efe6fd..74de71b 100644 --- a/ipc/mojo/ipc_message_pipe_reader.h +++ b/ipc/mojo/ipc_message_pipe_reader.h
@@ -10,8 +10,8 @@ #include "base/compiler_specific.h" #include "base/memory/scoped_ptr.h" #include "ipc/ipc_message.h" -#include "mojo/public/c/environment/async_waiter.h" -#include "mojo/public/cpp/system/core.h" +#include "third_party/mojo/src/mojo/public/c/environment/async_waiter.h" +#include "third_party/mojo/src/mojo/public/cpp/system/core.h" namespace IPC { namespace internal {
diff --git a/ipc/mojo/ipc_mojo_bootstrap.cc b/ipc/mojo/ipc_mojo_bootstrap.cc index a95dae2..591ced0 100644 --- a/ipc/mojo/ipc_mojo_bootstrap.cc +++ b/ipc/mojo/ipc_mojo_bootstrap.cc
@@ -8,7 +8,7 @@ #include "base/process/process_handle.h" #include "ipc/ipc_message_utils.h" #include "ipc/ipc_platform_file.h" -#include "mojo/edk/embedder/platform_channel_pair.h" +#include "third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h" namespace IPC {
diff --git a/ipc/mojo/ipc_mojo_bootstrap.h b/ipc/mojo/ipc_mojo_bootstrap.h index 72675538..eb1a987 100644 --- a/ipc/mojo/ipc_mojo_bootstrap.h +++ b/ipc/mojo/ipc_mojo_bootstrap.h
@@ -9,7 +9,7 @@ #include "base/process/process_handle.h" #include "ipc/ipc_channel.h" #include "ipc/ipc_listener.h" -#include "mojo/edk/embedder/scoped_platform_handle.h" +#include "third_party/mojo/src/mojo/edk/embedder/scoped_platform_handle.h" namespace IPC {
diff --git a/ipc/mojo/ipc_mojo_perftest.cc b/ipc/mojo/ipc_mojo_perftest.cc index 8bdac8c9..7147cd07 100644 --- a/ipc/mojo/ipc_mojo_perftest.cc +++ b/ipc/mojo/ipc_mojo_perftest.cc
@@ -6,7 +6,7 @@ #include "ipc/ipc_perftest_support.h" #include "ipc/mojo/ipc_channel_mojo.h" #include "ipc/mojo/ipc_channel_mojo_host.h" -#include "mojo/edk/embedder/test_embedder.h" +#include "third_party/mojo/src/mojo/edk/embedder/test_embedder.h" namespace {
diff --git a/ipc/mojo/run_all_unittests.cc b/ipc/mojo/run_all_unittests.cc index cc5b102..fe2bf85c 100644 --- a/ipc/mojo/run_all_unittests.cc +++ b/ipc/mojo/run_all_unittests.cc
@@ -6,7 +6,7 @@ #include "base/bind.h" #include "base/test/launcher/unit_test_launcher.h" #include "base/test/test_suite.h" -#include "mojo/edk/embedder/test_embedder.h" +#include "third_party/mojo/src/mojo/edk/embedder/test_embedder.h" #if defined(OS_ANDROID) #include "base/android/jni_android.h"
diff --git a/jingle/glue/pseudotcp_adapter_unittest.cc b/jingle/glue/pseudotcp_adapter_unittest.cc index ef031a9..212a2d0 100644 --- a/jingle/glue/pseudotcp_adapter_unittest.cc +++ b/jingle/glue/pseudotcp_adapter_unittest.cc
@@ -46,13 +46,13 @@ : volume_(volume), rate_(rate), level_(0.0), - last_update_(base::TimeTicks::HighResNow()) { + last_update_(base::TimeTicks::Now()) { } ~LeakyBucket() override {} bool DropNextPacket() override { - base::TimeTicks now = base::TimeTicks::HighResNow(); + base::TimeTicks now = base::TimeTicks::Now(); double interval = (now - last_update_).InSecondsF(); last_update_ = now; level_ = level_ + 1.0 - interval * rate_;
diff --git a/jingle/glue/thread_wrapper.cc b/jingle/glue/thread_wrapper.cc index d07b7468..f74fbb3 100644 --- a/jingle/glue/thread_wrapper.cc +++ b/jingle/glue/thread_wrapper.cc
@@ -30,16 +30,26 @@ // static void JingleThreadWrapper::EnsureForCurrentMessageLoop() { - if (JingleThreadWrapper::current() == NULL) { + if (JingleThreadWrapper::current() == nullptr) { base::MessageLoop* message_loop = base::MessageLoop::current(); - g_jingle_thread_wrapper.Get() - .Set(new JingleThreadWrapper(message_loop->message_loop_proxy())); - message_loop->AddDestructionObserver(current()); + scoped_ptr<JingleThreadWrapper> wrapper = + JingleThreadWrapper::WrapTaskRunner(message_loop->task_runner()); + message_loop->AddDestructionObserver(wrapper.release()); } DCHECK_EQ(rtc::Thread::Current(), current()); } +scoped_ptr<JingleThreadWrapper> JingleThreadWrapper::WrapTaskRunner( + scoped_refptr<base::SingleThreadTaskRunner> task_runner) { + DCHECK(!JingleThreadWrapper::current()); + DCHECK(task_runner->BelongsToCurrentThread()); + + scoped_ptr<JingleThreadWrapper> result(new JingleThreadWrapper(task_runner)); + g_jingle_thread_wrapper.Get().Set(result.get()); + return result.Pass(); +} + // static JingleThreadWrapper* JingleThreadWrapper::current() { return g_jingle_thread_wrapper.Get().Get(); @@ -47,8 +57,7 @@ JingleThreadWrapper::JingleThreadWrapper( scoped_refptr<base::SingleThreadTaskRunner> task_runner) - : rtc::Thread(new rtc::NullSocketServer()), - task_runner_(task_runner), + : task_runner_(task_runner), send_allowed_(false), last_task_id_(0), pending_send_event_(true, false), @@ -61,18 +70,19 @@ } JingleThreadWrapper::~JingleThreadWrapper() { - Clear(NULL, rtc::MQID_ANY, NULL); + DCHECK_EQ(this, JingleThreadWrapper::current()); + DCHECK_EQ(this, rtc::Thread::Current()); + + UnwrapCurrent(); + rtc::ThreadManager::Instance()->SetCurrentThread(nullptr); + rtc::MessageQueueManager::Remove(this); + g_jingle_thread_wrapper.Get().Set(nullptr); + + Clear(nullptr, rtc::MQID_ANY, nullptr); } void JingleThreadWrapper::WillDestroyCurrentMessageLoop() { - DCHECK_EQ(rtc::Thread::Current(), current()); - UnwrapCurrent(); - g_jingle_thread_wrapper.Get().Set(NULL); - rtc::ThreadManager::Instance()->SetCurrentThread(NULL); - rtc::MessageQueueManager::Remove(this); - rtc::SocketServer* ss = socketserver(); delete this; - delete ss; } void JingleThreadWrapper::Post( @@ -133,7 +143,7 @@ return; JingleThreadWrapper* current_thread = JingleThreadWrapper::current(); - DCHECK(current_thread != NULL) << "Send() can be called only from a " + DCHECK(current_thread != nullptr) << "Send() can be called only from a " "thread that has JingleThreadWrapper."; rtc::Message message; @@ -180,7 +190,7 @@ void JingleThreadWrapper::ProcessPendingSends() { while (true) { - PendingSend* pending_send = NULL; + PendingSend* pending_send = nullptr; { base::AutoLock auto_lock(lock_); if (!pending_send_messages_.empty()) { @@ -240,7 +250,7 @@ if (have_message) { if (message.message_id == rtc::MQID_DISPOSE) { - DCHECK(message.phandler == NULL); + DCHECK(message.phandler == nullptr); delete message.pdata; } else { message.phandler->OnMessage(&message);
diff --git a/jingle/glue/thread_wrapper.h b/jingle/glue/thread_wrapper.h index 6a045bf..7969d2bc6a 100644 --- a/jingle/glue/thread_wrapper.h +++ b/jingle/glue/thread_wrapper.h
@@ -35,13 +35,15 @@ // MessageLoop is destroyed. static void EnsureForCurrentMessageLoop(); - // Returns thread wrapper for the current thread. NULL is returned - // if EnsureForCurrentMessageLoop() has never been called for this - // thread. + // Creates JingleThreadWrapper for |task_runner| that runs tasks on the + // current thread. + static scoped_ptr<JingleThreadWrapper> WrapTaskRunner( + scoped_refptr<base::SingleThreadTaskRunner> task_runner); + + // Returns thread wrapper for the current thread or nullptr if it doesn't + // exist. static JingleThreadWrapper* current(); - explicit JingleThreadWrapper( - scoped_refptr<base::SingleThreadTaskRunner> task_runner); ~JingleThreadWrapper() override; // Sets whether the thread can be used to send messages @@ -95,6 +97,9 @@ typedef std::map<int, rtc::Message> MessagesQueue; struct PendingSend; + explicit JingleThreadWrapper( + scoped_refptr<base::SingleThreadTaskRunner> task_runner); + void PostTaskInternal( int delay_ms, rtc::MessageHandler* handler, uint32 message_id, rtc::MessageData* data);
diff --git a/media/BUILD.gn b/media/BUILD.gn index 688c6a7..4a8c1d9d 100644 --- a/media/BUILD.gn +++ b/media/BUILD.gn
@@ -226,6 +226,8 @@ "video/capture/win/video_capture_device_mf_win.h", "video/capture/win/video_capture_device_win.cc", "video/capture/win/video_capture_device_win.h", + "video/fake_video_encode_accelerator.cc", + "video/fake_video_encode_accelerator.h", "video/h264_poc.cc", "video/h264_poc.h", "video/picture.cc",
diff --git a/media/audio/clockless_audio_sink.cc b/media/audio/clockless_audio_sink.cc index 88e25b8af8..77f70571 100644 --- a/media/audio/clockless_audio_sink.cc +++ b/media/audio/clockless_audio_sink.cc
@@ -44,10 +44,10 @@ base::PlatformThread::YieldCurrentThread(); } else if (start.is_null()) { // First time we processed some audio, so record the starting time. - start = base::TimeTicks::HighResNow(); + start = base::TimeTicks::Now(); } else { // Keep track of the last time data was rendered. - playback_time_ = base::TimeTicks::HighResNow() - start; + playback_time_ = base::TimeTicks::Now() - start; } } }
diff --git a/media/base/android/media_codec_bridge.cc b/media/base/android/media_codec_bridge.cc index ee847b7..d6bd2d9d 100644 --- a/media/base/android/media_codec_bridge.cc +++ b/media/base/android/media_codec_bridge.cc
@@ -238,10 +238,14 @@ // HW-acceleration but it doesn't. Android Media guidance is that the // "OMX.google" prefix is always used for SW decoders, so that's what we // use. "OMX.SEC.*" codec is Samsung software implementation - report it - // as unaccelerated as well. + // as unaccelerated as well. Also temporary blacklist Exynos and MediaTek + // devices while HW decoder video freezes and distortions are + // investigated - http://crbug.com/446974. if (codec_name.length() > 0) { return (StartsWithASCII(codec_name, "OMX.google.", true) || - StartsWithASCII(codec_name, "OMX.SEC.", true)); + StartsWithASCII(codec_name, "OMX.SEC.", true) || + StartsWithASCII(codec_name, "OMX.MTK.", true) || + StartsWithASCII(codec_name, "OMX.Exynos.", true)); } return true; }
diff --git a/media/base/audio_bus_perftest.cc b/media/base/audio_bus_perftest.cc index 0af023507..71e8132 100644 --- a/media/base/audio_bus_perftest.cc +++ b/media/base/audio_bus_perftest.cc
@@ -18,22 +18,22 @@ scoped_ptr<T[]> interleaved(new T[frame_size]); const int byte_size = sizeof(T); - base::TimeTicks start = base::TimeTicks::HighResNow(); + base::TimeTicks start = base::TimeTicks::Now(); for (int i = 0; i < kBenchmarkIterations; ++i) { bus->ToInterleaved(bus->frames(), byte_size, interleaved.get()); } double total_time_milliseconds = - (base::TimeTicks::HighResNow() - start).InMillisecondsF(); + (base::TimeTicks::Now() - start).InMillisecondsF(); perf_test::PrintResult( "audio_bus_to_interleaved", "", trace_name, total_time_milliseconds / kBenchmarkIterations, "ms", true); - start = base::TimeTicks::HighResNow(); + start = base::TimeTicks::Now(); for (int i = 0; i < kBenchmarkIterations; ++i) { bus->FromInterleaved(interleaved.get(), bus->frames(), byte_size); } total_time_milliseconds = - (base::TimeTicks::HighResNow() - start).InMillisecondsF(); + (base::TimeTicks::Now() - start).InMillisecondsF(); perf_test::PrintResult( "audio_bus_from_interleaved", "", trace_name, total_time_milliseconds / kBenchmarkIterations, "ms", true);
diff --git a/media/base/audio_converter_perftest.cc b/media/base/audio_converter_perftest.cc index c6a4758..92bff29 100644 --- a/media/base/audio_converter_perftest.cc +++ b/media/base/audio_converter_perftest.cc
@@ -39,12 +39,12 @@ converter.AddInput(&fake_input2); converter.AddInput(&fake_input3); - base::TimeTicks start = base::TimeTicks::HighResNow(); + base::TimeTicks start = base::TimeTicks::Now(); for (int i = 0; i < kBenchmarkIterations; ++i) { converter.Convert(output_bus.get()); } double runs_per_second = kBenchmarkIterations / - (base::TimeTicks::HighResNow() - start).InSecondsF(); + (base::TimeTicks::Now() - start).InSecondsF(); perf_test::PrintResult( "audio_converter", "", trace_name, runs_per_second, "runs/s", true); }
diff --git a/media/base/audio_renderer.h b/media/base/audio_renderer.h index 668d919d..7d0e3d76 100644 --- a/media/base/audio_renderer.h +++ b/media/base/audio_renderer.h
@@ -25,7 +25,8 @@ virtual ~AudioRenderer(); // Initialize an AudioRenderer with |stream|, executing |init_cb| upon - // completion. + // completion. If initialization fails, only |init_cb| (not |error_cb|) will + // be called. // // |set_decryptor_ready_cb| is fired when a Decryptor is needed, i.e. when the // |stream| is encrypted. @@ -37,7 +38,7 @@ // // |ended_cb| is executed when audio rendering has reached the end of stream. // - // |error_cb| is executed if an error was encountered. + // |error_cb| is executed if an error was encountered after initialization. virtual void Initialize(DemuxerStream* stream, const PipelineStatusCB& init_cb, const SetDecryptorReadyCB& set_decryptor_ready_cb,
diff --git a/media/base/demuxer_perftest.cc b/media/base/demuxer_perftest.cc index 454f478f..42fc6e8 100644 --- a/media/base/demuxer_perftest.cc +++ b/media/base/demuxer_perftest.cc
@@ -187,11 +187,11 @@ StreamReader stream_reader(&demuxer, false); // Benchmark. - base::TimeTicks start = base::TimeTicks::HighResNow(); + base::TimeTicks start = base::TimeTicks::Now(); while (!stream_reader.IsDone()) { stream_reader.Read(); } - base::TimeTicks end = base::TimeTicks::HighResNow(); + base::TimeTicks end = base::TimeTicks::Now(); total_time += (end - start).InSecondsF(); demuxer.Stop(); QuitLoopWithStatus(&message_loop, PIPELINE_OK);
diff --git a/media/base/mock_filters.h b/media/base/mock_filters.h index 8a507b4..c8d1c822 100644 --- a/media/base/mock_filters.h +++ b/media/base/mock_filters.h
@@ -168,7 +168,7 @@ // Renderer implementation. MOCK_METHOD7(Initialize, void(DemuxerStreamProvider* demuxer_stream_provider, - const base::Closure& init_cb, + const PipelineStatusCB& init_cb, const StatisticsCB& statistics_cb, const BufferingStateCB& buffering_state_cb, const PaintCB& paint_cb,
diff --git a/media/base/pipeline.cc b/media/base/pipeline.cc index e8fa6c77..685aae6 100644 --- a/media/base/pipeline.cc +++ b/media/base/pipeline.cc
@@ -335,7 +335,7 @@ return InitializeDemuxer(done_cb); case kInitRenderer: - return InitializeRenderer(base::Bind(done_cb, PIPELINE_OK)); + return InitializeRenderer(done_cb); case kPlaying: // Report metadata the first time we enter the playing state. @@ -606,6 +606,7 @@ void Pipeline::SetCdmTask(CdmContext* cdm_context, const CdmAttachedCB& cdm_attached_cb) { + base::AutoLock auto_lock(lock_); if (!renderer_) { pending_cdm_context_ = cdm_context; cdm_attached_cb.Run(true); @@ -702,7 +703,7 @@ demuxer_->Initialize(this, done_cb, text_renderer_); } -void Pipeline::InitializeRenderer(const base::Closure& done_cb) { +void Pipeline::InitializeRenderer(const PipelineStatusCB& done_cb) { DCHECK(task_runner_->BelongsToCurrentThread()); if (!demuxer_->GetStream(DemuxerStream::AUDIO) &&
diff --git a/media/base/pipeline.h b/media/base/pipeline.h index 74b9c54..de3952b 100644 --- a/media/base/pipeline.h +++ b/media/base/pipeline.h
@@ -278,7 +278,7 @@ // Kicks off initialization for each media object, executing |done_cb| with // the result when completed. void InitializeDemuxer(const PipelineStatusCB& done_cb); - void InitializeRenderer(const base::Closure& done_cb); + void InitializeRenderer(const PipelineStatusCB& done_cb); void StateTransitionTask(PipelineStatus status);
diff --git a/media/base/pipeline_unittest.cc b/media/base/pipeline_unittest.cc index d6f1308..354b51e 100644 --- a/media/base/pipeline_unittest.cc +++ b/media/base/pipeline_unittest.cc
@@ -57,13 +57,6 @@ ACTION_TEMPLATE(PostCallback, HAS_1_TEMPLATE_PARAMS(int, k), - AND_0_VALUE_PARAMS()) { - return base::MessageLoop::current()->PostTask(FROM_HERE, - ::std::tr1::get<k>(args)); -} - -ACTION_TEMPLATE(PostCallback, - HAS_1_TEMPLATE_PARAMS(int, k), AND_1_VALUE_PARAMS(p0)) { return base::MessageLoop::current()->PostTask( FROM_HERE, base::Bind(::std::tr1::get<k>(args), p0)); @@ -180,7 +173,7 @@ EXPECT_CALL(*renderer_, Initialize(_, _, _, _, _, _, _)) .WillOnce(DoAll(SaveArg<3>(&buffering_state_cb_), SaveArg<5>(&ended_cb_), - PostCallback<1>())); + PostCallback<1>(PIPELINE_OK))); EXPECT_CALL(*renderer_, HasAudio()).WillRepeatedly(Return(audio_stream())); EXPECT_CALL(*renderer_, HasVideo()).WillRepeatedly(Return(video_stream())); } @@ -865,13 +858,12 @@ if (stop_or_error == kStop) { EXPECT_CALL(*renderer_, Initialize(_, _, _, _, _, _, _)) .WillOnce(DoAll(Stop(pipeline_.get(), stop_cb), - PostCallback<1>())); + PostCallback<1>(PIPELINE_OK))); ExpectPipelineStopAndDestroyPipeline(); } else { status = PIPELINE_ERROR_INITIALIZATION_FAILED; EXPECT_CALL(*renderer_, Initialize(_, _, _, _, _, _, _)) - .WillOnce( - DoAll(RunCallback<6>(status), PostCallback<1>())); + .WillOnce(PostCallback<1>(status)); } EXPECT_CALL(*demuxer_, Stop()); @@ -880,7 +872,7 @@ EXPECT_CALL(*renderer_, Initialize(_, _, _, _, _, _, _)) .WillOnce(DoAll(SaveArg<3>(&buffering_state_cb_), - PostCallback<1>())); + PostCallback<1>(PIPELINE_OK))); EXPECT_CALL(callbacks_, OnMetadata(_));
diff --git a/media/base/renderer.h b/media/base/renderer.h index 206a8d3..1c7afbd98 100644 --- a/media/base/renderer.h +++ b/media/base/renderer.h
@@ -29,10 +29,11 @@ virtual ~Renderer(); // Initializes the Renderer with |demuxer_stream_provider|, executing - // |init_cb| upon completion. If initialization failed, fires |error_cb| - // before |init_cb|. |demuxer_stream_provider| must be valid throughout the - // lifetime of the Renderer object. |init_cb| must only be run after this - // method has returned. + // |init_cb| upon completion. If initialization fails, only |init_cb| (not + // |error_cb|) should be called. |demuxer_stream_provider| must be valid for + // the lifetime of the Renderer object. |init_cb| must only be run after this + // method has returned. Firing |init_cb| may result in the immediate + // destruction of the caller, so it must be run only prior to returning. // // Permanent callbacks: // - |statistics_cb|: Executed periodically with rendering statistics. @@ -41,9 +42,9 @@ // ignored if the Renderer handles the painting by itself. Can // be called from any thread. // - |ended_cb|: Executed when rendering has reached the end of stream. - // - |error_cb|: Executed if any error was encountered during rendering. + // - |error_cb|: Executed if any error was encountered after initialization. virtual void Initialize(DemuxerStreamProvider* demuxer_stream_provider, - const base::Closure& init_cb, + const PipelineStatusCB& init_cb, const StatisticsCB& statistics_cb, const BufferingStateCB& buffering_state_cb, const PaintCB& paint_cb,
diff --git a/media/base/sinc_resampler_perftest.cc b/media/base/sinc_resampler_perftest.cc index b54056af..5ee33481 100644 --- a/media/base/sinc_resampler_perftest.cc +++ b/media/base/sinc_resampler_perftest.cc
@@ -32,7 +32,7 @@ float (*convolve_fn)(const float*, const float*, const float*, double), bool aligned, const std::string& trace_name) { - base::TimeTicks start = base::TimeTicks::HighResNow(); + base::TimeTicks start = base::TimeTicks::Now(); for (int i = 0; i < kBenchmarkIterations; ++i) { convolve_fn(resampler->get_kernel_for_testing() + (aligned ? 0 : 1), resampler->get_kernel_for_testing(), @@ -40,7 +40,7 @@ kKernelInterpolationFactor); } double total_time_milliseconds = - (base::TimeTicks::HighResNow() - start).InMillisecondsF(); + (base::TimeTicks::Now() - start).InMillisecondsF(); perf_test::PrintResult("sinc_resampler_convolve", "", trace_name,
diff --git a/media/base/sinc_resampler_unittest.cc b/media/base/sinc_resampler_unittest.cc index b0bac3a..f3f45c4 100644 --- a/media/base/sinc_resampler_unittest.cc +++ b/media/base/sinc_resampler_unittest.cc
@@ -141,11 +141,10 @@ kSampleRateRatio, SincResampler::kDefaultRequestSize, base::Bind(&MockSource::ProvideInput, base::Unretained(&mock_source))); - base::TimeTicks start = base::TimeTicks::HighResNow(); + base::TimeTicks start = base::TimeTicks::Now(); for (int i = 1; i < 10000; ++i) resampler.SetRatio(1.0 / i); - double total_time_c_ms = - (base::TimeTicks::HighResNow() - start).InMillisecondsF(); + double total_time_c_ms = (base::TimeTicks::Now() - start).InMillisecondsF(); printf("SetRatio() took %.2fms.\n", total_time_c_ms); }
diff --git a/media/base/vector_math_perftest.cc b/media/base/vector_math_perftest.cc index 2cf4691..ae3b54e 100644 --- a/media/base/vector_math_perftest.cc +++ b/media/base/vector_math_perftest.cc
@@ -36,7 +36,7 @@ bool aligned, const std::string& test_name, const std::string& trace_name) { - TimeTicks start = TimeTicks::HighResNow(); + TimeTicks start = TimeTicks::Now(); for (int i = 0; i < kBenchmarkIterations; ++i) { fn(input_vector_.get(), kScale, @@ -44,7 +44,7 @@ output_vector_.get()); } double total_time_milliseconds = - (TimeTicks::HighResNow() - start).InMillisecondsF(); + (TimeTicks::Now() - start).InMillisecondsF(); perf_test::PrintResult(test_name, "", trace_name, @@ -58,12 +58,12 @@ int len, const std::string& test_name, const std::string& trace_name) { - TimeTicks start = TimeTicks::HighResNow(); + TimeTicks start = TimeTicks::Now(); for (int i = 0; i < kEWMABenchmarkIterations; ++i) { fn(0.5f, input_vector_.get(), len, 0.1f); } double total_time_milliseconds = - (TimeTicks::HighResNow() - start).InMillisecondsF(); + (TimeTicks::Now() - start).InMillisecondsF(); perf_test::PrintResult(test_name, "", trace_name,
diff --git a/media/base/video_decoder.h b/media/base/video_decoder.h index bba581dc..c49e0dcd 100644 --- a/media/base/video_decoder.h +++ b/media/base/video_decoder.h
@@ -84,8 +84,9 @@ // called again). // // After decoding is finished the decoder calls |output_cb| specified in - // Initialize() for each decoded frame. |output_cb| may be called before or - // after |decode_cb|. + // Initialize() for each decoded frame. In general |output_cb| may be called + // before or after |decode_cb|, but software decoders normally call + // |output_cb| before calling |decode_cb|, i.e. while Decode() is pending. // // If |buffer| is an EOS buffer then the decoder must be flushed, i.e. // |output_cb| must be called for each frame pending in the queue and
diff --git a/media/base/video_renderer.h b/media/base/video_renderer.h index 94196eb..1e44333 100644 --- a/media/base/video_renderer.h +++ b/media/base/video_renderer.h
@@ -33,7 +33,8 @@ virtual ~VideoRenderer(); // Initializes a VideoRenderer with |stream|, executing |init_cb| upon - // completion. + // completion. If initialization fails, only |init_cb| (not |error_cb|) will + // be called. // // |set_decryptor_ready_cb| is fired when a Decryptor is needed, i.e. when the // |stream| is encrypted. @@ -49,7 +50,7 @@ // // |ended_cb| is executed when video rendering has reached the end of stream. // - // |error_cb| is executed if an error was encountered. + // |error_cb| is executed if an error was encountered after initialization. // // |get_time_cb| is used to query the current media playback time. virtual void Initialize(DemuxerStream* stream,
diff --git a/media/base/yuv_convert_perftest.cc b/media/base/yuv_convert_perftest.cc index c6cacaf..7d3d64c 100644 --- a/media/base/yuv_convert_perftest.cc +++ b/media/base/yuv_convert_perftest.cc
@@ -67,7 +67,7 @@ TEST_F(YUVConvertPerfTest, ConvertYUVToRGB32Row_SSE) { ASSERT_TRUE(base::CPU().has_sse()); - base::TimeTicks start = base::TimeTicks::HighResNow(); + base::TimeTicks start = base::TimeTicks::Now(); for (int i = 0; i < kPerfTestIterations; ++i) { for (int row = 0; row < kSourceHeight; ++row) { int chroma_row = row / 2; @@ -80,8 +80,7 @@ GetLookupTable(YV12)); } } - double total_time_seconds = - (base::TimeTicks::HighResNow() - start).InSecondsF(); + double total_time_seconds = (base::TimeTicks::Now() - start).InSecondsF(); perf_test::PrintResult( "yuv_convert_perftest", "", "ConvertYUVToRGB32Row_SSE", kPerfTestIterations / total_time_seconds, "runs/s", true); @@ -96,7 +95,7 @@ const int kSourceDx = 80000; // This value means a scale down. - base::TimeTicks start = base::TimeTicks::HighResNow(); + base::TimeTicks start = base::TimeTicks::Now(); for (int i = 0; i < kPerfTestIterations; ++i) { for (int row = 0; row < kSourceHeight; ++row) { int chroma_row = row / 2; @@ -110,8 +109,7 @@ GetLookupTable(YV12)); } } - double total_time_seconds = - (base::TimeTicks::HighResNow() - start).InSecondsF(); + double total_time_seconds = (base::TimeTicks::Now() - start).InSecondsF(); perf_test::PrintResult( "yuv_convert_perftest", "", "ScaleYUVToRGB32Row_SSE", kPerfTestIterations / total_time_seconds, "runs/s", true); @@ -123,7 +121,7 @@ const int kSourceDx = 80000; // This value means a scale down. - base::TimeTicks start = base::TimeTicks::HighResNow(); + base::TimeTicks start = base::TimeTicks::Now(); for (int i = 0; i < kPerfTestIterations; ++i) { for (int row = 0; row < kSourceHeight; ++row) { int chroma_row = row / 2; @@ -137,8 +135,7 @@ GetLookupTable(YV12)); } } - double total_time_seconds = - (base::TimeTicks::HighResNow() - start).InSecondsF(); + double total_time_seconds = (base::TimeTicks::Now() - start).InSecondsF(); perf_test::PrintResult( "yuv_convert_perftest", "", "LinearScaleYUVToRGB32Row_SSE", kPerfTestIterations / total_time_seconds, "runs/s", true);
diff --git a/media/blink/webcontentdecryptionmoduleaccess_impl.cc b/media/blink/webcontentdecryptionmoduleaccess_impl.cc index 9971829..ec4e9194 100644 --- a/media/blink/webcontentdecryptionmoduleaccess_impl.cc +++ b/media/blink/webcontentdecryptionmoduleaccess_impl.cc
@@ -25,17 +25,20 @@ WebContentDecryptionModuleAccessImpl* WebContentDecryptionModuleAccessImpl::Create( const blink::WebString& key_system, + const blink::WebMediaKeySystemConfiguration& configuration, const blink::WebSecurityOrigin& security_origin, CdmFactory* cdm_factory) { - return new WebContentDecryptionModuleAccessImpl(key_system, security_origin, - cdm_factory); + return new WebContentDecryptionModuleAccessImpl(key_system, configuration, + security_origin, cdm_factory); } WebContentDecryptionModuleAccessImpl::WebContentDecryptionModuleAccessImpl( const blink::WebString& key_system, + const blink::WebMediaKeySystemConfiguration& configuration, const blink::WebSecurityOrigin& security_origin, CdmFactory* cdm_factory) : key_system_(key_system), + configuration_(configuration), security_origin_(security_origin), cdm_factory_(cdm_factory) { } @@ -43,6 +46,11 @@ WebContentDecryptionModuleAccessImpl::~WebContentDecryptionModuleAccessImpl() { } +blink::WebMediaKeySystemConfiguration +WebContentDecryptionModuleAccessImpl::getConfiguration() { + return configuration_; +} + void WebContentDecryptionModuleAccessImpl::createContentDecryptionModule( blink::WebContentDecryptionModuleResult result) { // This method needs to run asynchronously, as it may need to load the CDM.
diff --git a/media/blink/webcontentdecryptionmoduleaccess_impl.h b/media/blink/webcontentdecryptionmoduleaccess_impl.h index 2d288ca..9d54823 100644 --- a/media/blink/webcontentdecryptionmoduleaccess_impl.h +++ b/media/blink/webcontentdecryptionmoduleaccess_impl.h
@@ -9,6 +9,7 @@ #include "base/memory/scoped_ptr.h" #include "media/base/cdm_factory.h" #include "third_party/WebKit/public/platform/WebContentDecryptionModuleAccess.h" +#include "third_party/WebKit/public/platform/WebMediaKeySystemConfiguration.h" #include "third_party/WebKit/public/platform/WebString.h" #include "third_party/WebKit/public/web/WebSecurityOrigin.h" @@ -23,23 +24,27 @@ public: static WebContentDecryptionModuleAccessImpl* Create( const blink::WebString& key_system, + const blink::WebMediaKeySystemConfiguration& configuration, const blink::WebSecurityOrigin& security_origin, CdmFactory* cdm_factory); virtual ~WebContentDecryptionModuleAccessImpl(); // blink::WebContentDecryptionModuleAccess interface. + virtual blink::WebMediaKeySystemConfiguration getConfiguration(); virtual void createContentDecryptionModule( - blink::WebContentDecryptionModuleResult result) override; + blink::WebContentDecryptionModuleResult result); private: WebContentDecryptionModuleAccessImpl( const blink::WebString& key_system, + const blink::WebMediaKeySystemConfiguration& configuration, const blink::WebSecurityOrigin& security_origin, CdmFactory* cdm_factory); DISALLOW_COPY_AND_ASSIGN(WebContentDecryptionModuleAccessImpl); blink::WebString key_system_; + blink::WebMediaKeySystemConfiguration configuration_; blink::WebSecurityOrigin security_origin_; CdmFactory* cdm_factory_; };
diff --git a/media/blink/webencryptedmediaclient_impl.cc b/media/blink/webencryptedmediaclient_impl.cc index af7b7f4..dd1eaaca 100644 --- a/media/blink/webencryptedmediaclient_impl.cc +++ b/media/blink/webencryptedmediaclient_impl.cc
@@ -160,34 +160,30 @@ } // 7.2 Let implementation be the implementation of keySystem. - // 7.3 Follow the steps for the first matching condition from the following - // list: - // - If supportedConfigurations was not provided, run the Is Key System - // Supported? algorithm and if successful, resolve promise with access - // and abort these steps. - // TODO(sandersd): Remove pending the resolution of - // https://github.com/w3c/encrypted-media/issues/1. + // 7.3 For each value in supportedConfigurations, run the GetSupported + // Configuration algorithm and if successful, resolve promise with access + // and abort these steps. const blink::WebVector<blink::WebMediaKeySystemConfiguration>& configurations = request.supportedConfigurations(); + + // TODO(sandersd): Remove once Blink requires the configurations parameter for + // requestMediaKeySystemAccess(). if (configurations.isEmpty()) { request.requestSucceeded(WebContentDecryptionModuleAccessImpl::Create( - request.keySystem(), request.securityOrigin(), cdm_factory_.get())); + request.keySystem(), blink::WebMediaKeySystemConfiguration(), + request.securityOrigin(), cdm_factory_.get())); return; } - // - Otherwise, for each value in supportedConfigurations, run the - // GetSuppored Configuration algorithm and if successful, resolve - // promise with access and abort these steps. for (size_t i = 0; i < configurations.size(); i++) { const blink::WebMediaKeySystemConfiguration& candidate = configurations[i]; blink::WebMediaKeySystemConfiguration accumulated_configuration; if (GetSupportedConfiguration(key_system, candidate, request.securityOrigin(), &accumulated_configuration)) { - // TODO(sandersd): Pass the accumulated configuration along. - // http://crbug.com/447059. request.requestSucceeded(WebContentDecryptionModuleAccessImpl::Create( - request.keySystem(), request.securityOrigin(), cdm_factory_.get())); + request.keySystem(), accumulated_configuration, + request.securityOrigin(), cdm_factory_.get())); return; } }
diff --git a/media/cast/BUILD.gn b/media/cast/BUILD.gn index 632b334..c10a990 100644 --- a/media/cast/BUILD.gn +++ b/media/cast/BUILD.gn
@@ -301,8 +301,6 @@ "test/end2end_unittest.cc", "test/fake_receiver_time_offset_estimator.cc", "test/fake_receiver_time_offset_estimator.h", - "test/fake_video_encode_accelerator.cc", - "test/fake_video_encode_accelerator.h", "test/utility/audio_utility_unittest.cc", "test/utility/barcode_unittest.cc", ]
diff --git a/media/cast/cast_testing.gypi b/media/cast/cast_testing.gypi index 6a554e0..12199b5 100644 --- a/media/cast/cast_testing.gypi +++ b/media/cast/cast_testing.gypi
@@ -123,8 +123,6 @@ 'test/fake_receiver_time_offset_estimator.h', 'test/fake_single_thread_task_runner.cc', 'test/fake_single_thread_task_runner.h', - 'test/fake_video_encode_accelerator.cc', - 'test/fake_video_encode_accelerator.h', 'test/utility/audio_utility_unittest.cc', 'test/utility/barcode_unittest.cc', ], # source @@ -149,8 +147,6 @@ 'test/cast_benchmarks.cc', 'test/fake_single_thread_task_runner.cc', 'test/fake_single_thread_task_runner.h', - 'test/fake_video_encode_accelerator.cc', - 'test/fake_video_encode_accelerator.h', 'test/utility/test_util.cc', 'test/utility/test_util.h', ], # source
diff --git a/media/cast/sender/external_video_encoder_unittest.cc b/media/cast/sender/external_video_encoder_unittest.cc index e48066d5..6cc1911e 100644 --- a/media/cast/sender/external_video_encoder_unittest.cc +++ b/media/cast/sender/external_video_encoder_unittest.cc
@@ -12,8 +12,8 @@ #include "media/cast/cast_environment.h" #include "media/cast/sender/external_video_encoder.h" #include "media/cast/test/fake_single_thread_task_runner.h" -#include "media/cast/test/fake_video_encode_accelerator.h" #include "media/cast/test/utility/video_utility.h" +#include "media/video/fake_video_encode_accelerator.h" #include "testing/gmock/include/gmock/gmock.h" namespace media { @@ -133,8 +133,7 @@ task_runner_, task_runner_); - fake_vea_ = new test::FakeVideoEncodeAccelerator(task_runner_, - &stored_bitrates_); + fake_vea_ = new media::FakeVideoEncodeAccelerator(task_runner_); scoped_ptr<VideoEncodeAccelerator> fake_vea(fake_vea_); VEAFactory vea_factory(task_runner_, fake_vea.Pass()); video_encoder_.reset(new ExternalVideoEncoder( @@ -156,8 +155,7 @@ } base::SimpleTestTickClock* testing_clock_; // Owned by CastEnvironment. - test::FakeVideoEncodeAccelerator* fake_vea_; // Owned by video_encoder_. - std::vector<uint32> stored_bitrates_; + media::FakeVideoEncodeAccelerator* fake_vea_; // Owned by video_encoder_. scoped_refptr<TestVideoEncoderCallback> test_video_encoder_callback_; VideoSenderConfig video_config_; scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_; @@ -194,12 +192,12 @@ video_frame_, testing_clock_->NowTicks(), frame_encoded_callback)); task_runner_->RunTasks(); } + ASSERT_EQ(1u, fake_vea_->stored_bitrates().size()); + EXPECT_EQ(2000u, fake_vea_->stored_bitrates()[0]); + // We need to run the task to cleanup the GPU instance. video_encoder_.reset(NULL); task_runner_->RunTasks(); - - ASSERT_EQ(1u, stored_bitrates_.size()); - EXPECT_EQ(2000u, stored_bitrates_[0]); } TEST_F(ExternalVideoEncoderTest, StreamHeader) { @@ -238,9 +236,8 @@ task_runner, task_runner)); - std::vector<uint32> stored_bitrates; scoped_ptr<VideoEncodeAccelerator> fake_vea( - new test::FakeVideoEncodeAccelerator(task_runner, &stored_bitrates)); + new media::FakeVideoEncodeAccelerator(task_runner)); VEAFactory vea_factory(task_runner, fake_vea.Pass()); scoped_ptr<ExternalVideoEncoder> video_encoder(new ExternalVideoEncoder(
diff --git a/media/cast/sender/h264_vt_encoder.cc b/media/cast/sender/h264_vt_encoder.cc index 33923488c..5e253ed 100644 --- a/media/cast/sender/h264_vt_encoder.cc +++ b/media/cast/sender/h264_vt_encoder.cc
@@ -5,12 +5,14 @@ #include "media/cast/sender/h264_vt_encoder.h" #include <string> +#include <vector> #include "base/big_endian.h" #include "base/bind.h" #include "base/bind_helpers.h" #include "base/location.h" #include "base/logging.h" +#include "base/macros.h" #include "media/base/mac/corevideo_glue.h" #include "media/base/mac/video_frame_mac.h" #include "media/cast/sender/video_frame_factory.h" @@ -43,6 +45,21 @@ &kCFTypeDictionaryValueCallBacks)); } +base::ScopedCFTypeRef<CFArrayRef> ArrayWithIntegers(const std::vector<int>& v) { + std::vector<CFNumberRef> numbers; + numbers.reserve(v.size()); + for (const int i : v) { + numbers.push_back(CFNumberCreate(nullptr, kCFNumberSInt32Type, &i)); + } + base::ScopedCFTypeRef<CFArrayRef> array(CFArrayCreate( + kCFAllocatorDefault, reinterpret_cast<const void**>(&numbers[0]), + numbers.size(), &kCFTypeArrayCallBacks)); + for (CFNumberRef number : numbers) { + CFRelease(number); + } + return array; +} + template <typename NalSizeType> void CopyNalsToAnnexB(char* avcc_buffer, const size_t avcc_size, @@ -257,11 +274,20 @@ kCFBooleanTrue); #endif + // Certain encoders prefer kCVPixelFormatType_422YpCbCr8, which is not + // supported through VideoFrame. We can force 420 formats to be used instead. + const int formats[] = { + kCVPixelFormatType_420YpCbCr8Planar, + CoreVideoGlue::kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange}; + base::ScopedCFTypeRef<CFArrayRef> formats_array = ArrayWithIntegers( + std::vector<int>(formats, formats + arraysize(formats))); + base::ScopedCFTypeRef<CFDictionaryRef> buffer_attributes = + DictionaryWithKeyValue(kCVPixelBufferPixelFormatTypeKey, formats_array); + VTCompressionSessionRef session; OSStatus status = videotoolbox_glue_->VTCompressionSessionCreate( kCFAllocatorDefault, video_config.width, video_config.height, - CoreMediaGlue::kCMVideoCodecType_H264, encoder_spec, - nullptr /* sourceImageBufferAttributes */, + CoreMediaGlue::kCMVideoCodecType_H264, encoder_spec, buffer_attributes, nullptr /* compressedDataAllocator */, &H264VideoToolboxEncoder::CompressionCallback, reinterpret_cast<void*>(this), &session);
diff --git a/media/cast/sender/video_sender_unittest.cc b/media/cast/sender/video_sender_unittest.cc index ab9ac4c..5c207d5 100644 --- a/media/cast/sender/video_sender_unittest.cc +++ b/media/cast/sender/video_sender_unittest.cc
@@ -18,9 +18,9 @@ #include "media/cast/sender/video_frame_factory.h" #include "media/cast/sender/video_sender.h" #include "media/cast/test/fake_single_thread_task_runner.h" -#include "media/cast/test/fake_video_encode_accelerator.h" #include "media/cast/test/utility/default_config.h" #include "media/cast/test/utility/video_utility.h" +#include "media/video/fake_video_encode_accelerator.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -133,7 +133,8 @@ class VideoSenderTest : public ::testing::Test { protected: - VideoSenderTest() { + VideoSenderTest() + : stored_bitrates_(NULL) { testing_clock_ = new base::SimpleTestTickClock(); testing_clock_->Advance(base::TimeTicks::Now() - base::TimeTicks()); task_runner_ = new test::FakeSingleThreadTaskRunner(testing_clock_); @@ -191,9 +192,9 @@ CastInitializationStatus status = STATUS_VIDEO_UNINITIALIZED; if (external) { - test::FakeVideoEncodeAccelerator* fake_vea = - new test::FakeVideoEncodeAccelerator( - task_runner_, &stored_bitrates_); + media::FakeVideoEncodeAccelerator* fake_vea = + new media::FakeVideoEncodeAccelerator(task_runner_); + stored_bitrates_ = &fake_vea->stored_bitrates(); fake_vea->SetWillInitializationSucceed(expect_init_success); scoped_ptr<VideoEncodeAccelerator> fake_vea_owner(fake_vea); video_sender_.reset( @@ -253,7 +254,7 @@ scoped_ptr<CastTransportSenderImpl> transport_sender_; scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_; scoped_ptr<PeerVideoSender> video_sender_; - std::vector<uint32> stored_bitrates_; + const std::vector<uint32>* stored_bitrates_; // Owned by |video_sender_|. scoped_refptr<CastEnvironment> cast_environment_; int last_pixel_value_; base::TimeTicks first_frame_timestamp_; @@ -288,7 +289,7 @@ // Fixed bitrate is used for external encoder. Bitrate is only once // to the encoder. - EXPECT_EQ(1u, stored_bitrates_.size()); + EXPECT_EQ(1u, stored_bitrates_->size()); video_sender_.reset(NULL); task_runner_->RunTasks(); }
diff --git a/media/cast/test/fake_video_encode_accelerator.cc b/media/cast/test/fake_video_encode_accelerator.cc deleted file mode 100644 index 23a6fb3..0000000 --- a/media/cast/test/fake_video_encode_accelerator.cc +++ /dev/null
@@ -1,121 +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 "media/cast/test/fake_video_encode_accelerator.h" - -#include "base/bind.h" -#include "base/location.h" -#include "base/logging.h" -#include "base/single_thread_task_runner.h" - -namespace media { -namespace cast { -namespace test { - -static const unsigned int kMinimumInputCount = 1; -static const size_t kMinimumOutputBufferSize = 123456; - -FakeVideoEncodeAccelerator::FakeVideoEncodeAccelerator( - const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, - std::vector<uint32>* stored_bitrates) - : task_runner_(task_runner), - stored_bitrates_(stored_bitrates), - client_(NULL), - first_(true), - will_initialization_succeed_(true), - weak_this_factory_(this) { - DCHECK(stored_bitrates_); -} - -FakeVideoEncodeAccelerator::~FakeVideoEncodeAccelerator() { - weak_this_factory_.InvalidateWeakPtrs(); -} - -std::vector<VideoEncodeAccelerator::SupportedProfile> -FakeVideoEncodeAccelerator::GetSupportedProfiles() { - return std::vector<VideoEncodeAccelerator::SupportedProfile>(); -} - -bool FakeVideoEncodeAccelerator::Initialize( - media::VideoFrame::Format input_format, - const gfx::Size& input_visible_size, - VideoCodecProfile output_profile, - uint32 initial_bitrate, - Client* client) { - if (!will_initialization_succeed_) - return false; - client_ = client; - if (output_profile != media::VP8PROFILE_ANY && - output_profile != media::H264PROFILE_MAIN) { - return false; - } - task_runner_->PostTask( - FROM_HERE, - base::Bind(&FakeVideoEncodeAccelerator::DoRequireBitstreamBuffers, - weak_this_factory_.GetWeakPtr(), - kMinimumInputCount, - input_visible_size, - kMinimumOutputBufferSize)); - return true; -} - -void FakeVideoEncodeAccelerator::Encode(const scoped_refptr<VideoFrame>& frame, - bool force_keyframe) { - DCHECK(client_); - DCHECK(!available_buffer_ids_.empty()); - - // Fake that we have encoded the frame; resulting in using the full output - // buffer. - int32 id = available_buffer_ids_.front(); - available_buffer_ids_.pop_front(); - - bool is_key_fame = force_keyframe; - if (first_) { - is_key_fame = true; - first_ = false; - } - task_runner_->PostTask( - FROM_HERE, - base::Bind(&FakeVideoEncodeAccelerator::DoBitstreamBufferReady, - weak_this_factory_.GetWeakPtr(), - id, - kMinimumOutputBufferSize, - is_key_fame)); -} - -void FakeVideoEncodeAccelerator::UseOutputBitstreamBuffer( - const BitstreamBuffer& buffer) { - available_buffer_ids_.push_back(buffer.id()); -} - -void FakeVideoEncodeAccelerator::RequestEncodingParametersChange( - uint32 bitrate, - uint32 framerate) { - stored_bitrates_->push_back(bitrate); -} - -void FakeVideoEncodeAccelerator::Destroy() { delete this; } - -void FakeVideoEncodeAccelerator::SendDummyFrameForTesting(bool key_frame) { - DoBitstreamBufferReady(0, 23, key_frame); -} - -void FakeVideoEncodeAccelerator::DoRequireBitstreamBuffers( - unsigned int input_count, - const gfx::Size& input_coded_size, - size_t output_buffer_size) const { - client_->RequireBitstreamBuffers( - input_count, input_coded_size, output_buffer_size); -} - -void FakeVideoEncodeAccelerator::DoBitstreamBufferReady( - int32 bitstream_buffer_id, - size_t payload_size, - bool key_frame) const { - client_->BitstreamBufferReady(bitstream_buffer_id, payload_size, key_frame); -} - -} // namespace test -} // namespace cast -} // namespace media
diff --git a/media/ffmpeg/ffmpeg_common_unittest.cc b/media/ffmpeg/ffmpeg_common_unittest.cc index 0d9bdc9..ff07307 100644 --- a/media/ffmpeg/ffmpeg_common_unittest.cc +++ b/media/ffmpeg/ffmpeg_common_unittest.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "base/logging.h" +#include "base/memory/scoped_ptr.h" #include "media/ffmpeg/ffmpeg_common.h" #include "media/filters/ffmpeg_glue.h" #include "testing/gtest/include/gtest/gtest.h" @@ -88,6 +89,17 @@ EXPECT_EQ(0, exploded.millisecond); } +#if defined(ALLOCATOR_SHIM) && defined(GTEST_HAS_DEATH_TEST) +TEST_F(FFmpegCommonTest, WinAllocatorShimDeathTest) { + scoped_ptr<char, base::FreeDeleter> ptr; + // INT_MAX - 128 is carefully chosen to be below the default limit for + // ffmpeg allocations, but above the maximum allowed limit by the allocator + // shim, so we can be certain the code is being hit. + EXPECT_DEATH(ptr.reset(static_cast<char*>(av_malloc(INT_MAX - 128))), ""); + ASSERT_TRUE(!ptr); +} +#endif + TEST_F(FFmpegCommonTest, UTCDateToTime_Invalid) { const char* invalid_date_strings[] = { "",
diff --git a/media/filters/ffmpeg_video_decoder.cc b/media/filters/ffmpeg_video_decoder.cc index c1ca0bd..a269afb 100644 --- a/media/filters/ffmpeg_video_decoder.cc +++ b/media/filters/ffmpeg_video_decoder.cc
@@ -240,6 +240,8 @@ if (buffer->end_of_stream()) state_ = kDecodeFinished; + // VideoDecoderShim expects that |decode_cb| is called only after + // |output_cb_|. decode_cb_bound.Run(kOk); }
diff --git a/media/filters/renderer_impl.cc b/media/filters/renderer_impl.cc index a2b0d99e..b8005d4 100644 --- a/media/filters/renderer_impl.cc +++ b/media/filters/renderer_impl.cc
@@ -50,11 +50,14 @@ video_renderer_.reset(); audio_renderer_.reset(); - FireAllPendingCallbacks(); + if (!init_cb_.is_null()) + base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_ABORT); + else if (!flush_cb_.is_null()) + base::ResetAndReturn(&flush_cb_).Run(); } void RendererImpl::Initialize(DemuxerStreamProvider* demuxer_stream_provider, - const base::Closure& init_cb, + const PipelineStatusCB& init_cb, const StatisticsCB& statistics_cb, const BufferingStateCB& buffering_state_cb, const PaintCB& paint_cb, @@ -262,16 +265,19 @@ DVLOG(1) << __FUNCTION__ << ": " << status; DCHECK(task_runner_->BelongsToCurrentThread()); - if (status != PIPELINE_OK) - OnError(status); - // OnError() may be fired at any time by the renderers, even if they thought // they initialized successfully (due to delayed output device setup). if (state_ != STATE_INITIALIZING) { + DCHECK(init_cb_.is_null()); audio_renderer_.reset(); return; } + if (status != PIPELINE_OK) { + base::ResetAndReturn(&init_cb_).Run(status); + return; + } + DCHECK(!init_cb_.is_null()); InitializeVideoRenderer(); } @@ -308,12 +314,10 @@ DVLOG(1) << __FUNCTION__ << ": " << status; DCHECK(task_runner_->BelongsToCurrentThread()); - if (status != PIPELINE_OK) - OnError(status); - // OnError() may be fired at any time by the renderers, even if they thought // they initialized successfully (due to delayed output device setup). if (state_ != STATE_INITIALIZING) { + DCHECK(init_cb_.is_null()); audio_renderer_.reset(); video_renderer_.reset(); return; @@ -321,6 +325,11 @@ DCHECK(!init_cb_.is_null()); + if (status != PIPELINE_OK) { + base::ResetAndReturn(&init_cb_).Run(status); + return; + } + if (audio_renderer_) { time_source_ = audio_renderer_->GetTimeSource(); } else { @@ -331,7 +340,7 @@ state_ = STATE_PLAYING; DCHECK(time_source_); DCHECK(audio_renderer_ || video_renderer_); - base::ResetAndReturn(&init_cb_).Run(); + base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); } void RendererImpl::FlushAudioRenderer() { @@ -549,20 +558,17 @@ if (state_ == STATE_ERROR) return; + const State old_state = state_; state_ = STATE_ERROR; - // Pipeline will destroy |this| as the result of error. + if (old_state == STATE_INITIALIZING) { + base::ResetAndReturn(&init_cb_).Run(error); + return; + } + + // After OnError() returns, the pipeline may destroy |this|. base::ResetAndReturn(&error_cb_).Run(error); - FireAllPendingCallbacks(); -} - -void RendererImpl::FireAllPendingCallbacks() { - DCHECK(task_runner_->BelongsToCurrentThread()); - - if (!init_cb_.is_null()) - base::ResetAndReturn(&init_cb_).Run(); - if (!flush_cb_.is_null()) base::ResetAndReturn(&flush_cb_).Run(); }
diff --git a/media/filters/renderer_impl.h b/media/filters/renderer_impl.h index 6a65bc00..f84b3bfe 100644 --- a/media/filters/renderer_impl.h +++ b/media/filters/renderer_impl.h
@@ -44,7 +44,7 @@ // Renderer implementation. void Initialize(DemuxerStreamProvider* demuxer_stream_provider, - const base::Closure& init_cb, + const PipelineStatusCB& init_cb, const StatisticsCB& statistics_cb, const BufferingStateCB& buffering_state_cb, const PaintCB& paint_cb, @@ -120,8 +120,6 @@ // Callback executed when a runtime error happens. void OnError(PipelineStatus error); - void FireAllPendingCallbacks(); - State state_; // Task runner used to execute pipeline tasks. @@ -137,7 +135,7 @@ PaintCB paint_cb_; // Temporary callback used for Initialize() and Flush(). - base::Closure init_cb_; + PipelineStatusCB init_cb_; base::Closure flush_cb_; scoped_ptr<AudioRenderer> audio_renderer_;
diff --git a/media/filters/renderer_impl_unittest.cc b/media/filters/renderer_impl_unittest.cc index ec8e3826..d8bb49e 100644 --- a/media/filters/renderer_impl_unittest.cc +++ b/media/filters/renderer_impl_unittest.cc
@@ -43,7 +43,7 @@ CallbackHelper() {} virtual ~CallbackHelper() {} - MOCK_METHOD0(OnInitialize, void()); + MOCK_METHOD1(OnInitialize, void(PipelineStatus)); MOCK_METHOD0(OnFlushed, void()); MOCK_METHOD0(OnEnded, void()); MOCK_METHOD1(OnError, void(PipelineStatus)); @@ -103,10 +103,7 @@ } void InitializeAndExpect(PipelineStatus start_status) { - if (start_status != PIPELINE_OK) - EXPECT_CALL(callbacks_, OnError(start_status)); - - EXPECT_CALL(callbacks_, OnInitialize()); + EXPECT_CALL(callbacks_, OnInitialize(start_status)); if (start_status == PIPELINE_OK && audio_stream_) { EXPECT_CALL(*audio_renderer_, GetTimeSource())
diff --git a/media/filters/vpx_video_decoder.cc b/media/filters/vpx_video_decoder.cc index 40d4cc9..96fbaa4 100644 --- a/media/filters/vpx_video_decoder.cc +++ b/media/filters/vpx_video_decoder.cc
@@ -354,10 +354,12 @@ return; } - base::ResetAndReturn(&decode_cb_).Run(kOk); - if (video_frame.get()) output_cb_.Run(video_frame); + + // VideoDecoderShim expects that |decode_cb| is called only after + // |output_cb_|. + base::ResetAndReturn(&decode_cb_).Run(kOk); } bool VpxVideoDecoder::VpxDecode(const scoped_refptr<DecoderBuffer>& buffer,
diff --git a/media/media.gyp b/media/media.gyp index d785ecb..6fe8230 100644 --- a/media/media.gyp +++ b/media/media.gyp
@@ -574,6 +574,8 @@ 'video/capture/win/video_capture_device_mf_win.h', 'video/capture/win/video_capture_device_win.cc', 'video/capture/win/video_capture_device_win.h', + 'video/fake_video_encode_accelerator.cc', + 'video/fake_video_encode_accelerator.h', 'video/h264_poc.cc', 'video/h264_poc.h', 'video/picture.cc',
diff --git a/media/midi/midi_manager_alsa.cc b/media/midi/midi_manager_alsa.cc index 37cbbebb..e4cadfb 100644 --- a/media/midi/midi_manager_alsa.cc +++ b/media/midi/midi_manager_alsa.cc
@@ -392,8 +392,7 @@ // Read available incoming MIDI data. snd_seq_event_t* event; int err = snd_seq_event_input(in_client_, &event); - double timestamp = - (base::TimeTicks::HighResNow() - base::TimeTicks()).InSecondsF(); + double timestamp = (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF(); if (err == -ENOSPC) { VLOG(1) << "snd_seq_event_input detected buffer overrun";
diff --git a/media/midi/usb_midi_device_android.cc b/media/midi/usb_midi_device_android.cc index 8f93c3d..ff58e62 100644 --- a/media/midi/usb_midi_device_android.cc +++ b/media/midi/usb_midi_device_android.cc
@@ -56,7 +56,7 @@ const uint8* head = bytes.size() ? &bytes[0] : NULL; delegate_->ReceiveUsbMidiData(this, endpoint_number, head, bytes.size(), - base::TimeTicks::HighResNow()); + base::TimeTicks::Now()); } bool UsbMidiDeviceAndroid::RegisterUsbMidiDevice(JNIEnv* env) {
diff --git a/media/mojo/DEPS b/media/mojo/DEPS index cc40af5..fe3c60e 100644 --- a/media/mojo/DEPS +++ b/media/mojo/DEPS
@@ -2,5 +2,5 @@ "+mojo/application", "+mojo/common", "+mojo/converters", - "+mojo/public", + "+third_party/mojo/src/mojo/public", ]
diff --git a/media/mojo/services/mojo_cdm.cc b/media/mojo/services/mojo_cdm.cc index 24d5905..88c5848 100644 --- a/media/mojo/services/mojo_cdm.cc +++ b/media/mojo/services/mojo_cdm.cc
@@ -9,9 +9,9 @@ #include "media/base/cdm_key_information.h" #include "media/base/cdm_promise.h" #include "media/mojo/services/media_type_converters.h" -#include "mojo/public/cpp/application/connect.h" -#include "mojo/public/cpp/bindings/interface_impl.h" -#include "mojo/public/interfaces/application/service_provider.mojom.h" +#include "third_party/mojo/src/mojo/public/cpp/application/connect.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_impl.h" +#include "third_party/mojo/src/mojo/public/interfaces/application/service_provider.mojom.h" #include "url/gurl.h" namespace media {
diff --git a/media/mojo/services/mojo_cdm_promise.h b/media/mojo/services/mojo_cdm_promise.h index 233d5b12..9e6a507a 100644 --- a/media/mojo/services/mojo_cdm_promise.h +++ b/media/mojo/services/mojo_cdm_promise.h
@@ -9,7 +9,7 @@ #include "media/base/cdm_promise.h" #include "media/mojo/interfaces/content_decryption_module.mojom.h" #include "media/mojo/services/mojo_type_trait.h" -#include "mojo/public/cpp/bindings/callback.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/callback.h" namespace media {
diff --git a/media/mojo/services/mojo_cdm_service.h b/media/mojo/services/mojo_cdm_service.h index da8f372..77f6149 100644 --- a/media/mojo/services/mojo_cdm_service.h +++ b/media/mojo/services/mojo_cdm_service.h
@@ -11,7 +11,7 @@ #include "base/memory/weak_ptr.h" #include "media/base/media_keys.h" #include "media/mojo/interfaces/content_decryption_module.mojom.h" -#include "mojo/public/cpp/bindings/interface_impl.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_impl.h" namespace media {
diff --git a/media/mojo/services/mojo_demuxer_stream_adapter.cc b/media/mojo/services/mojo_demuxer_stream_adapter.cc index ca04816..52139fc 100644 --- a/media/mojo/services/mojo_demuxer_stream_adapter.cc +++ b/media/mojo/services/mojo_demuxer_stream_adapter.cc
@@ -8,7 +8,7 @@ #include "base/callback_helpers.h" #include "media/base/decoder_buffer.h" #include "media/mojo/services/media_type_converters.h" -#include "mojo/public/cpp/system/data_pipe.h" +#include "third_party/mojo/src/mojo/public/cpp/system/data_pipe.h" namespace media {
diff --git a/media/mojo/services/mojo_demuxer_stream_impl.cc b/media/mojo/services/mojo_demuxer_stream_impl.cc index ffc79143..b5f24de 100644 --- a/media/mojo/services/mojo_demuxer_stream_impl.cc +++ b/media/mojo/services/mojo_demuxer_stream_impl.cc
@@ -11,8 +11,8 @@ #include "media/base/video_decoder_config.h" #include "media/mojo/interfaces/demuxer_stream.mojom.h" #include "media/mojo/services/media_type_converters.h" -#include "mojo/public/cpp/bindings/interface_impl.h" -#include "mojo/public/cpp/system/data_pipe.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_impl.h" +#include "third_party/mojo/src/mojo/public/cpp/system/data_pipe.h" namespace media {
diff --git a/media/mojo/services/mojo_demuxer_stream_impl.h b/media/mojo/services/mojo_demuxer_stream_impl.h index ec22040..adec06d 100644 --- a/media/mojo/services/mojo_demuxer_stream_impl.h +++ b/media/mojo/services/mojo_demuxer_stream_impl.h
@@ -9,7 +9,7 @@ #include "base/memory/weak_ptr.h" #include "media/base/demuxer_stream.h" #include "media/mojo/interfaces/demuxer_stream.mojom.h" -#include "mojo/public/cpp/bindings/interface_impl.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_impl.h" namespace media { class DemuxerStream;
diff --git a/media/mojo/services/mojo_media_application.cc b/media/mojo/services/mojo_media_application.cc index 145dec69..24f6e29 100644 --- a/media/mojo/services/mojo_media_application.cc +++ b/media/mojo/services/mojo_media_application.cc
@@ -7,11 +7,11 @@ #include "base/strings/utf_string_conversions.h" #include "media/mojo/services/mojo_renderer_service.h" #include "mojo/application/application_runner_chromium.h" -#include "mojo/public/c/system/main.h" -#include "mojo/public/cpp/application/application_connection.h" -#include "mojo/public/cpp/application/application_delegate.h" -#include "mojo/public/cpp/application/application_impl.h" -#include "mojo/public/cpp/application/interface_factory_impl.h" +#include "third_party/mojo/src/mojo/public/c/system/main.h" +#include "third_party/mojo/src/mojo/public/cpp/application/application_connection.h" +#include "third_party/mojo/src/mojo/public/cpp/application/application_delegate.h" +#include "third_party/mojo/src/mojo/public/cpp/application/application_impl.h" +#include "third_party/mojo/src/mojo/public/cpp/application/interface_factory_impl.h" namespace media {
diff --git a/media/mojo/services/mojo_renderer_factory.h b/media/mojo/services/mojo_renderer_factory.h index 5ebcffa87..2aa6cfc9 100644 --- a/media/mojo/services/mojo_renderer_factory.h +++ b/media/mojo/services/mojo_renderer_factory.h
@@ -8,7 +8,7 @@ #include "media/base/media_export.h" #include "media/base/renderer_factory.h" #include "media/mojo/interfaces/media_renderer.mojom.h" -#include "mojo/public/cpp/bindings/interface_ptr.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_ptr.h" namespace media {
diff --git a/media/mojo/services/mojo_renderer_impl.cc b/media/mojo/services/mojo_renderer_impl.cc index c1770316..bf422a3 100644 --- a/media/mojo/services/mojo_renderer_impl.cc +++ b/media/mojo/services/mojo_renderer_impl.cc
@@ -11,9 +11,9 @@ #include "media/base/bind_to_current_loop.h" #include "media/base/demuxer_stream_provider.h" #include "media/mojo/services/mojo_demuxer_stream_impl.h" -#include "mojo/public/cpp/application/connect.h" -#include "mojo/public/cpp/bindings/interface_impl.h" -#include "mojo/public/interfaces/application/service_provider.mojom.h" +#include "third_party/mojo/src/mojo/public/cpp/application/connect.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_impl.h" +#include "third_party/mojo/src/mojo/public/interfaces/application/service_provider.mojom.h" namespace media { @@ -35,7 +35,7 @@ // TODO(xhwang): Support |paint_cb| if needed. void MojoRendererImpl::Initialize( DemuxerStreamProvider* demuxer_stream_provider, - const base::Closure& init_cb, + const PipelineStatusCB& init_cb, const StatisticsCB& statistics_cb, const BufferingStateCB& buffering_state_cb, const PaintCB& /* paint_cb */, @@ -202,15 +202,14 @@ if (init_cb_.is_null()) // We have initialized already. error_cb_.Run(PIPELINE_ERROR_DECODE); else - error_cb_.Run(PIPELINE_ERROR_COULD_NOT_RENDER); + init_cb_.Run(PIPELINE_ERROR_COULD_NOT_RENDER); } void MojoRendererImpl::OnInitialized() { DVLOG(1) << __FUNCTION__; DCHECK(task_runner_->BelongsToCurrentThread()); - DCHECK(!init_cb_.is_null()); - - base::ResetAndReturn(&init_cb_).Run(); + if (!init_cb_.is_null()) + base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); } } // namespace media
diff --git a/media/mojo/services/mojo_renderer_impl.h b/media/mojo/services/mojo_renderer_impl.h index bd6a607..c891892 100644 --- a/media/mojo/services/mojo_renderer_impl.h +++ b/media/mojo/services/mojo_renderer_impl.h
@@ -34,7 +34,7 @@ // Renderer implementation. void Initialize(DemuxerStreamProvider* demuxer_stream_provider, - const base::Closure& init_cb, + const PipelineStatusCB& init_cb, const StatisticsCB& statistics_cb, const BufferingStateCB& buffering_state_cb, const PaintCB& paint_cb, @@ -74,7 +74,7 @@ // Callbacks passed to Initialize() that we forward messages from // |remote_media_renderer_| through. - base::Closure init_cb_; + PipelineStatusCB init_cb_; base::Closure ended_cb_; PipelineStatusCB error_cb_; BufferingStateCB buffering_state_cb_;
diff --git a/media/mojo/services/mojo_renderer_service.cc b/media/mojo/services/mojo_renderer_service.cc index 562ae18..8224986 100644 --- a/media/mojo/services/mojo_renderer_service.cc +++ b/media/mojo/services/mojo_renderer_service.cc
@@ -125,9 +125,12 @@ } void MojoRendererService::OnRendererInitializeDone( - const mojo::Closure& callback) { + const mojo::Closure& callback, PipelineStatus status) { DVLOG(1) << __FUNCTION__; + if (status != PIPELINE_OK && state_ != STATE_ERROR) + OnError(status); + if (state_ == STATE_ERROR) { renderer_.reset(); } else {
diff --git a/media/mojo/services/mojo_renderer_service.h b/media/mojo/services/mojo_renderer_service.h index 7ad544b..0c6b7ee 100644 --- a/media/mojo/services/mojo_renderer_service.h +++ b/media/mojo/services/mojo_renderer_service.h
@@ -14,7 +14,7 @@ #include "media/base/buffering_state.h" #include "media/base/pipeline_status.h" #include "media/mojo/interfaces/media_renderer.mojom.h" -#include "mojo/public/cpp/bindings/interface_impl.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_impl.h" namespace mojo { class ApplicationConnection; @@ -57,7 +57,8 @@ void OnStreamReady(const mojo::Closure& callback); // Called when |audio_renderer_| initialization has completed. - void OnRendererInitializeDone(const mojo::Closure& callback); + void OnRendererInitializeDone(const mojo::Closure& callback, + PipelineStatus status); // Callback executed by filters to update statistics. void OnUpdateStatistics(const PipelineStatistics& stats);
diff --git a/media/mojo/services/mojo_type_trait.h b/media/mojo/services/mojo_type_trait.h index d041b76..19d87a12 100644 --- a/media/mojo/services/mojo_type_trait.h +++ b/media/mojo/services/mojo_type_trait.h
@@ -6,8 +6,8 @@ #define MEDIA_MOJO_SERVICES_MOJO_TYPE_TRAIT_H_ #include "media/base/media_keys.h" -#include "mojo/public/cpp/bindings/array.h" -#include "mojo/public/cpp/bindings/string.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/array.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/string.h" namespace media {
diff --git a/media/test/DEPS b/media/test/DEPS index ef8ad28..5f8633a 100644 --- a/media/test/DEPS +++ b/media/test/DEPS
@@ -1,3 +1,3 @@ include_rules = [ - "+mojo/public", + "+third_party/mojo/src/mojo/public", ]
diff --git a/media/test/pipeline_integration_perftest.cc b/media/test/pipeline_integration_perftest.cc index 81efc909c..e09de39e 100644 --- a/media/test/pipeline_integration_perftest.cc +++ b/media/test/pipeline_integration_perftest.cc
@@ -24,7 +24,7 @@ PIPELINE_OK, pipeline.Start(filename, PipelineIntegrationTestBase::kClockless)); - base::TimeTicks start = base::TimeTicks::HighResNow(); + base::TimeTicks start = base::TimeTicks::Now(); pipeline.Play(); ASSERT_TRUE(pipeline.WaitUntilOnEnded()); @@ -35,7 +35,7 @@ if (audio_only) { time_seconds += pipeline.GetAudioTime().InSecondsF(); } else { - time_seconds += (base::TimeTicks::HighResNow() - start).InSecondsF(); + time_seconds += (base::TimeTicks::Now() - start).InSecondsF(); } }
diff --git a/media/test/pipeline_integration_test.cc b/media/test/pipeline_integration_test.cc index c4782c6..d326a6c 100644 --- a/media/test/pipeline_integration_test.cc +++ b/media/test/pipeline_integration_test.cc
@@ -24,9 +24,9 @@ #if defined(MOJO_RENDERER) #include "media/mojo/services/mojo_renderer_impl.h" -#include "mojo/public/cpp/application/application_impl.h" -#include "mojo/public/cpp/application/application_test_base.h" -#include "mojo/public/cpp/application/connect.h" +#include "third_party/mojo/src/mojo/public/cpp/application/application_impl.h" +#include "third_party/mojo/src/mojo/public/cpp/application/application_test_base.h" +#include "third_party/mojo/src/mojo/public/cpp/application/connect.h" // TODO(dalecurtis): The mojo renderer is in another process, so we have no way // currently to get hashes for video and audio samples. This also means that
diff --git a/media/video/capture/linux/video_capture_device_chromeos.cc b/media/video/capture/linux/video_capture_device_chromeos.cc index abbc3b2..4a6b501f8 100644 --- a/media/video/capture/linux/video_capture_device_chromeos.cc +++ b/media/video/capture/linux/video_capture_device_chromeos.cc
@@ -41,14 +41,12 @@ private: friend class base::RefCountedThreadSafe<ScreenObserverDelegate>; - virtual ~ScreenObserverDelegate() { - DCHECK(!capture_device_); - } + ~ScreenObserverDelegate() override { DCHECK(!capture_device_); } - virtual void OnDisplayAdded(const gfx::Display& /*new_display*/) override {} - virtual void OnDisplayRemoved(const gfx::Display& /*old_display*/) override {} - virtual void OnDisplayMetricsChanged(const gfx::Display& display, - uint32_t metrics) override { + void OnDisplayAdded(const gfx::Display& /*new_display*/) override {} + void OnDisplayRemoved(const gfx::Display& /*old_display*/) override {} + void OnDisplayMetricsChanged(const gfx::Display& display, + uint32_t metrics) override { DCHECK(ui_task_runner_->BelongsToCurrentThread()); if (!(metrics & DISPLAY_METRIC_ROTATION)) return;
diff --git a/media/video/capture/linux/video_capture_device_chromeos.h b/media/video/capture/linux/video_capture_device_chromeos.h index 6a79cd09..50b77a9 100644 --- a/media/video/capture/linux/video_capture_device_chromeos.h +++ b/media/video/capture/linux/video_capture_device_chromeos.h
@@ -21,7 +21,7 @@ explicit VideoCaptureDeviceChromeOS( scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, const Name& device_name); - virtual ~VideoCaptureDeviceChromeOS(); + ~VideoCaptureDeviceChromeOS() override; private: class ScreenObserverDelegate;
diff --git a/media/video/fake_video_encode_accelerator.cc b/media/video/fake_video_encode_accelerator.cc new file mode 100644 index 0000000..4ca7a236 --- /dev/null +++ b/media/video/fake_video_encode_accelerator.cc
@@ -0,0 +1,140 @@ +// 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 "media/video/fake_video_encode_accelerator.h" + +#include "base/bind.h" +#include "base/location.h" +#include "base/logging.h" +#include "base/single_thread_task_runner.h" + +namespace media { + +static const unsigned int kMinimumInputCount = 1; +static const size_t kMinimumOutputBufferSize = 123456; + +FakeVideoEncodeAccelerator::FakeVideoEncodeAccelerator( + const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) + : task_runner_(task_runner), + will_initialization_succeed_(true), + client_(NULL), + next_frame_is_first_frame_(true), + weak_this_factory_(this) {} + +FakeVideoEncodeAccelerator::~FakeVideoEncodeAccelerator() { + weak_this_factory_.InvalidateWeakPtrs(); +} + +std::vector<VideoEncodeAccelerator::SupportedProfile> +FakeVideoEncodeAccelerator::GetSupportedProfiles() { + std::vector<VideoEncodeAccelerator::SupportedProfile> profiles; + SupportedProfile profile; + profile.max_resolution.SetSize(1920, 1088); + profile.max_framerate_numerator = 30; + profile.max_framerate_denominator = 1; + + profile.profile = media::H264PROFILE_MAIN; + profiles.push_back(profile); + profile.profile = media::VP8PROFILE_ANY; + profiles.push_back(profile); + return profiles; +} + +bool FakeVideoEncodeAccelerator::Initialize( + VideoFrame::Format input_format, + const gfx::Size& input_visible_size, + VideoCodecProfile output_profile, + uint32 initial_bitrate, + Client* client) { + if (!will_initialization_succeed_) { + return false; + } + if (output_profile == VIDEO_CODEC_PROFILE_UNKNOWN || + output_profile > VIDEO_CODEC_PROFILE_MAX) { + return false; + } + client_ = client; + task_runner_->PostTask( + FROM_HERE, + base::Bind(&FakeVideoEncodeAccelerator::DoRequireBitstreamBuffers, + weak_this_factory_.GetWeakPtr(), + kMinimumInputCount, + input_visible_size, + kMinimumOutputBufferSize)); + return true; +} + +void FakeVideoEncodeAccelerator::Encode( + const scoped_refptr<VideoFrame>& frame, + bool force_keyframe) { + DCHECK(client_); + queued_frames_.push(force_keyframe); + EncodeTask(); +} + +void FakeVideoEncodeAccelerator::UseOutputBitstreamBuffer( + const BitstreamBuffer& buffer) { + available_buffers_.push_back(buffer); + EncodeTask(); +} + +void FakeVideoEncodeAccelerator::RequestEncodingParametersChange( + uint32 bitrate, + uint32 framerate) { + stored_bitrates_.push_back(bitrate); +} + +void FakeVideoEncodeAccelerator::Destroy() { delete this; } + +void FakeVideoEncodeAccelerator::SendDummyFrameForTesting(bool key_frame) { + task_runner_->PostTask( + FROM_HERE, + base::Bind(&FakeVideoEncodeAccelerator::DoBitstreamBufferReady, + weak_this_factory_.GetWeakPtr(), + 0, + 23, + key_frame)); +} + +void FakeVideoEncodeAccelerator::SetWillInitializationSucceed( + bool will_initialization_succeed) { + will_initialization_succeed_ = will_initialization_succeed; +} + +void FakeVideoEncodeAccelerator::DoRequireBitstreamBuffers( + unsigned int input_count, + const gfx::Size& input_coded_size, + size_t output_buffer_size) const { + client_->RequireBitstreamBuffers( + input_count, input_coded_size, output_buffer_size); +} + +void FakeVideoEncodeAccelerator::EncodeTask() { + while (!queued_frames_.empty() && !available_buffers_.empty()) { + bool force_key_frame = queued_frames_.front(); + queued_frames_.pop(); + int32 bitstream_buffer_id = available_buffers_.front().id(); + available_buffers_.pop_front(); + bool key_frame = next_frame_is_first_frame_ || force_key_frame; + next_frame_is_first_frame_ = false; + task_runner_->PostTask( + FROM_HERE, + base::Bind(&FakeVideoEncodeAccelerator::DoBitstreamBufferReady, + weak_this_factory_.GetWeakPtr(), + bitstream_buffer_id, + kMinimumOutputBufferSize, + key_frame)); + } +} + +void FakeVideoEncodeAccelerator::DoBitstreamBufferReady( + int32 bitstream_buffer_id, + size_t payload_size, + bool key_frame) const { + client_->BitstreamBufferReady(bitstream_buffer_id, + payload_size, + key_frame); +} + +} // namespace media
diff --git a/media/cast/test/fake_video_encode_accelerator.h b/media/video/fake_video_encode_accelerator.h similarity index 65% rename from media/cast/test/fake_video_encode_accelerator.h rename to media/video/fake_video_encode_accelerator.h index 65cc36c..6c7c348b 100644 --- a/media/cast/test/fake_video_encode_accelerator.h +++ b/media/video/fake_video_encode_accelerator.h
@@ -2,78 +2,84 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef MEDIA_CAST_TEST_FAKE_MOCK_VIDEO_ENCODE_ACCELERATOR_H_ -#define MEDIA_CAST_TEST_FAKE_MOCK_VIDEO_ENCODE_ACCELERATOR_H_ - -#include "media/video/video_encode_accelerator.h" +#ifndef MEDIA_VIDEO_FAKE_VIDEO_ENCODE_ACCELERATOR_H_ +#define MEDIA_VIDEO_FAKE_VIDEO_ENCODE_ACCELERATOR_H_ #include <list> +#include <queue> #include <vector> #include "base/memory/weak_ptr.h" #include "media/base/bitstream_buffer.h" +#include "media/base/media_export.h" +#include "media/video/video_encode_accelerator.h" namespace base { + class SingleThreadTaskRunner; + } // namespace base namespace media { -namespace cast { -namespace test { -class FakeVideoEncodeAccelerator : public VideoEncodeAccelerator { +class MEDIA_EXPORT FakeVideoEncodeAccelerator : public VideoEncodeAccelerator { public: explicit FakeVideoEncodeAccelerator( - const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, - std::vector<uint32>* stored_bitrates); + const scoped_refptr<base::SingleThreadTaskRunner>& task_runner); ~FakeVideoEncodeAccelerator() override; std::vector<VideoEncodeAccelerator::SupportedProfile> GetSupportedProfiles() override; - bool Initialize(media::VideoFrame::Format input_format, + bool Initialize(VideoFrame::Format input_format, const gfx::Size& input_visible_size, VideoCodecProfile output_profile, uint32 initial_bitrate, Client* client) override; - void Encode(const scoped_refptr<VideoFrame>& frame, bool force_keyframe) override; - void UseOutputBitstreamBuffer(const BitstreamBuffer& buffer) override; - void RequestEncodingParametersChange(uint32 bitrate, uint32 framerate) override; - void Destroy() override; - void SendDummyFrameForTesting(bool key_frame); - void SetWillInitializationSucceed(bool will_initialization_succeed) { - will_initialization_succeed_ = will_initialization_succeed; + const std::vector<uint32>& stored_bitrates() const { + return stored_bitrates_; } + void SendDummyFrameForTesting(bool key_frame); + void SetWillInitializationSucceed(bool will_initialization_succeed); private: void DoRequireBitstreamBuffers(unsigned int input_count, const gfx::Size& input_coded_size, size_t output_buffer_size) const; + void EncodeTask(); void DoBitstreamBufferReady(int32 bitstream_buffer_id, size_t payload_size, bool key_frame) const; + // Our original (constructor) calling message loop used for all tasks. const scoped_refptr<base::SingleThreadTaskRunner> task_runner_; - std::vector<uint32>* const stored_bitrates_; - VideoEncodeAccelerator::Client* client_; - bool first_; + std::vector<uint32> stored_bitrates_; bool will_initialization_succeed_; - std::list<int32> available_buffer_ids_; + VideoEncodeAccelerator::Client* client_; + + // Keeps track of if the current frame is the first encoded frame. This + // is used to force a fake key frame for the first encoded frame. + bool next_frame_is_first_frame_; + + // A queue containing the necessary data for incoming frames. The boolean + // represent whether the queued frame should force a key frame. + std::queue<bool> queued_frames_; + + // A list of buffers available for putting fake encoded frames in. + std::list<BitstreamBuffer> available_buffers_; base::WeakPtrFactory<FakeVideoEncodeAccelerator> weak_this_factory_; DISALLOW_COPY_AND_ASSIGN(FakeVideoEncodeAccelerator); }; -} // namespace test -} // namespace cast } // namespace media -#endif // MEDIA_CAST_TEST_FAKE_MOCK_VIDEO_ENCODE_ACCELERATOR_H_ +#endif // MEDIA_VIDEO_FAKE_VIDEO_ENCODE_ACCELERATOR_H_
diff --git a/mojo/DEPS b/mojo/DEPS index c37b8de..aa5b7ea 100644 --- a/mojo/DEPS +++ b/mojo/DEPS
@@ -2,6 +2,8 @@ "+base", "+build", "+mojo", - "-mojo/edk/system", "+testing", + "+third_party/mojo/src/mojo/edk", + "-third_party/mojo/src/mojo/edk/system", + "+third_party/mojo/src/mojo/public", ]
diff --git a/mojo/android/javatests/init_library.cc b/mojo/android/javatests/init_library.cc index c738981..958d8ee 100644 --- a/mojo/android/javatests/init_library.cc +++ b/mojo/android/javatests/init_library.cc
@@ -9,8 +9,8 @@ #include "mojo/android/javatests/mojo_test_case.h" #include "mojo/android/javatests/validation_test_util.h" #include "mojo/android/system/core_impl.h" -#include "mojo/edk/embedder/embedder.h" -#include "mojo/edk/embedder/simple_platform_support.h" +#include "third_party/mojo/src/mojo/edk/embedder/embedder.h" +#include "third_party/mojo/src/mojo/edk/embedder/simple_platform_support.h" namespace {
diff --git a/mojo/android/javatests/mojo_test_case.cc b/mojo/android/javatests/mojo_test_case.cc index 419d14d..74998a47 100644 --- a/mojo/android/javatests/mojo_test_case.cc +++ b/mojo/android/javatests/mojo_test_case.cc
@@ -15,7 +15,7 @@ #include "jni/MojoTestCase_jni.h" #include "mojo/common/message_pump_mojo.h" -#include "mojo/public/cpp/environment/environment.h" +#include "third_party/mojo/src/mojo/public/cpp/environment/environment.h" namespace {
diff --git a/mojo/android/javatests/validation_test_util.cc b/mojo/android/javatests/validation_test_util.cc index 2289e025..a01974fe 100644 --- a/mojo/android/javatests/validation_test_util.cc +++ b/mojo/android/javatests/validation_test_util.cc
@@ -9,7 +9,7 @@ #include "base/android/scoped_java_ref.h" #include "base/test/test_support_android.h" #include "jni/ValidationTestUtil_jni.h" -#include "mojo/public/cpp/bindings/tests/validation_test_input_parser.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/tests/validation_test_input_parser.h" namespace mojo { namespace android {
diff --git a/mojo/android/system/core_impl.cc b/mojo/android/system/core_impl.cc index 55a374e..4898eec 100644 --- a/mojo/android/system/core_impl.cc +++ b/mojo/android/system/core_impl.cc
@@ -13,9 +13,9 @@ #include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" #include "jni/CoreImpl_jni.h" -#include "mojo/public/c/environment/async_waiter.h" -#include "mojo/public/c/system/core.h" -#include "mojo/public/cpp/environment/environment.h" +#include "third_party/mojo/src/mojo/public/c/environment/async_waiter.h" +#include "third_party/mojo/src/mojo/public/c/system/core.h" +#include "third_party/mojo/src/mojo/public/cpp/environment/environment.h" namespace {
diff --git a/mojo/application/application_runner_chromium.cc b/mojo/application/application_runner_chromium.cc index e49b8e2..ed6d013a 100644 --- a/mojo/application/application_runner_chromium.cc +++ b/mojo/application/application_runner_chromium.cc
@@ -10,8 +10,8 @@ #include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" #include "mojo/common/message_pump_mojo.h" -#include "mojo/public/cpp/application/application_delegate.h" -#include "mojo/public/cpp/application/application_impl.h" +#include "third_party/mojo/src/mojo/public/cpp/application/application_delegate.h" +#include "third_party/mojo/src/mojo/public/cpp/application/application_impl.h" namespace mojo {
diff --git a/mojo/application/application_runner_chromium.h b/mojo/application/application_runner_chromium.h index 8671342..cb586850 100644 --- a/mojo/application/application_runner_chromium.h +++ b/mojo/application/application_runner_chromium.h
@@ -7,7 +7,7 @@ #include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" -#include "mojo/public/cpp/system/core.h" +#include "third_party/mojo/src/mojo/public/cpp/system/core.h" namespace mojo {
diff --git a/mojo/application/application_test_main_chromium.cc b/mojo/application/application_test_main_chromium.cc index ace886d..33c4084e 100644 --- a/mojo/application/application_test_main_chromium.cc +++ b/mojo/application/application_test_main_chromium.cc
@@ -3,8 +3,8 @@ // found in the LICENSE file. #include "base/at_exit.h" -#include "mojo/public/c/system/main.h" -#include "mojo/public/cpp/application/application_test_base.h" +#include "third_party/mojo/src/mojo/public/c/system/main.h" +#include "third_party/mojo/src/mojo/public/cpp/application/application_test_base.h" MojoResult MojoMain(MojoHandle shell_handle) { // An AtExitManager instance is needed to construct message loops.
diff --git a/mojo/cc/context_provider_mojo.cc b/mojo/cc/context_provider_mojo.cc index 16c6f8c..8e5411d 100644 --- a/mojo/cc/context_provider_mojo.cc +++ b/mojo/cc/context_provider_mojo.cc
@@ -5,7 +5,7 @@ #include "mojo/cc/context_provider_mojo.h" #include "base/logging.h" -#include "mojo/public/cpp/environment/environment.h" +#include "third_party/mojo/src/mojo/public/cpp/environment/environment.h" namespace mojo {
diff --git a/mojo/cc/context_provider_mojo.h b/mojo/cc/context_provider_mojo.h index 014b973..76cd19f 100644 --- a/mojo/cc/context_provider_mojo.h +++ b/mojo/cc/context_provider_mojo.h
@@ -7,8 +7,8 @@ #include "base/macros.h" #include "cc/output/context_provider.h" -#include "mojo/public/c/gles2/gles2.h" -#include "mojo/public/cpp/system/core.h" +#include "third_party/mojo/src/mojo/public/c/gles2/gles2.h" +#include "third_party/mojo/src/mojo/public/cpp/system/core.h" namespace mojo {
diff --git a/mojo/common/DEPS b/mojo/common/DEPS index e8ac4288..f3ee1c891 100644 --- a/mojo/common/DEPS +++ b/mojo/common/DEPS
@@ -2,5 +2,5 @@ # common must not depend on embedder. "-mojo", "+mojo/common", - "+mojo/public", + "+third_party/mojo/src/mojo/public", ]
diff --git a/mojo/common/common_type_converters.h b/mojo/common/common_type_converters.h index 7b0260a..8ba2708 100644 --- a/mojo/common/common_type_converters.h +++ b/mojo/common/common_type_converters.h
@@ -8,9 +8,9 @@ #include "base/strings/string16.h" #include "base/strings/string_piece.h" #include "mojo/common/mojo_common_export.h" -#include "mojo/public/cpp/bindings/array.h" -#include "mojo/public/cpp/bindings/string.h" -#include "mojo/public/cpp/bindings/type_converter.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/array.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/string.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/type_converter.h" class GURL;
diff --git a/mojo/common/data_pipe_utils.h b/mojo/common/data_pipe_utils.h index dc2197b..65a0b8b 100644 --- a/mojo/common/data_pipe_utils.h +++ b/mojo/common/data_pipe_utils.h
@@ -9,7 +9,7 @@ #include "base/callback_forward.h" #include "mojo/common/mojo_common_export.h" -#include "mojo/public/cpp/system/core.h" +#include "third_party/mojo/src/mojo/public/cpp/system/core.h" namespace base { class FilePath;
diff --git a/mojo/common/handle_watcher.h b/mojo/common/handle_watcher.h index dfcb1451..9056ec4 100644 --- a/mojo/common/handle_watcher.h +++ b/mojo/common/handle_watcher.h
@@ -10,7 +10,7 @@ #include "base/memory/scoped_ptr.h" #include "base/run_loop.h" #include "mojo/common/mojo_common_export.h" -#include "mojo/public/cpp/system/core.h" +#include "third_party/mojo/src/mojo/public/cpp/system/core.h" namespace base { class Thread;
diff --git a/mojo/common/handle_watcher_unittest.cc b/mojo/common/handle_watcher_unittest.cc index 61913cdd..3323421 100644 --- a/mojo/common/handle_watcher_unittest.cc +++ b/mojo/common/handle_watcher_unittest.cc
@@ -15,9 +15,9 @@ #include "base/threading/thread.h" #include "mojo/common/message_pump_mojo.h" #include "mojo/common/time_helper.h" -#include "mojo/public/cpp/system/core.h" -#include "mojo/public/cpp/test_support/test_utils.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/mojo/src/mojo/public/cpp/system/core.h" +#include "third_party/mojo/src/mojo/public/cpp/test_support/test_utils.h" namespace mojo { namespace common {
diff --git a/mojo/common/message_pump_mojo.h b/mojo/common/message_pump_mojo.h index b313271d..899f9799 100644 --- a/mojo/common/message_pump_mojo.h +++ b/mojo/common/message_pump_mojo.h
@@ -14,7 +14,7 @@ #include "base/synchronization/lock.h" #include "base/time/time.h" #include "mojo/common/mojo_common_export.h" -#include "mojo/public/cpp/system/core.h" +#include "third_party/mojo/src/mojo/public/cpp/system/core.h" namespace mojo { namespace common {
diff --git a/mojo/common/message_pump_mojo_handler.h b/mojo/common/message_pump_mojo_handler.h index ba40f808..dd136edb 100644 --- a/mojo/common/message_pump_mojo_handler.h +++ b/mojo/common/message_pump_mojo_handler.h
@@ -6,7 +6,7 @@ #define MOJO_COMMON_MESSAGE_PUMP_MOJO_HANDLER_H_ #include "mojo/common/mojo_common_export.h" -#include "mojo/public/cpp/system/core.h" +#include "third_party/mojo/src/mojo/public/cpp/system/core.h" namespace mojo { namespace common {
diff --git a/mojo/common/message_pump_mojo_unittest.cc b/mojo/common/message_pump_mojo_unittest.cc index 09cbe54..5d695f6a56 100644 --- a/mojo/common/message_pump_mojo_unittest.cc +++ b/mojo/common/message_pump_mojo_unittest.cc
@@ -7,8 +7,8 @@ #include "base/message_loop/message_loop_test.h" #include "base/run_loop.h" #include "mojo/common/message_pump_mojo_handler.h" -#include "mojo/public/cpp/system/core.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/mojo/src/mojo/public/cpp/system/core.h" namespace mojo { namespace common {
diff --git a/mojo/environment/default_async_waiter_impl.h b/mojo/environment/default_async_waiter_impl.h index 5140e35..dea4621 100644 --- a/mojo/environment/default_async_waiter_impl.h +++ b/mojo/environment/default_async_waiter_impl.h
@@ -6,7 +6,7 @@ #define MOJO_ENVIRONMENT_DEFAULT_ASYNC_WAITER_IMPL_H_ #include "mojo/environment/mojo_environment_impl_export.h" -#include "mojo/public/c/environment/async_waiter.h" +#include "third_party/mojo/src/mojo/public/c/environment/async_waiter.h" namespace mojo { namespace internal {
diff --git a/mojo/environment/default_logger_impl.h b/mojo/environment/default_logger_impl.h index c87a727..ca73237 100644 --- a/mojo/environment/default_logger_impl.h +++ b/mojo/environment/default_logger_impl.h
@@ -6,7 +6,7 @@ #define MOJO_ENVIRONMENT_DEFAULT_LOGGER_IMPL_H_ #include "mojo/environment/mojo_environment_impl_export.h" -#include "mojo/public/c/environment/logger.h" +#include "third_party/mojo/src/mojo/public/c/environment/logger.h" namespace mojo { namespace internal {
diff --git a/mojo/environment/environment.cc b/mojo/environment/environment.cc index 418d89e6..ec181661 100644 --- a/mojo/environment/environment.cc +++ b/mojo/environment/environment.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 "mojo/public/cpp/environment/environment.h" +#include "third_party/mojo/src/mojo/public/cpp/environment/environment.h" #include "mojo/environment/default_async_waiter_impl.h" #include "mojo/environment/default_logger_impl.h"
diff --git a/mojo/nacl/generator/libmojo.cc.tmpl b/mojo/nacl/generator/libmojo.cc.tmpl index 7a70376..a58ad81 100644 --- a/mojo/nacl/generator/libmojo.cc.tmpl +++ b/mojo/nacl/generator/libmojo.cc.tmpl
@@ -4,10 +4,10 @@ {{generator_warning}} -#include "mojo/public/c/system/core.h" #include "native_client/src/public/chrome_main.h" #include "native_client/src/public/imc_syscalls.h" #include "native_client/src/public/imc_types.h" +#include "third_party/mojo/src/mojo/public/c/system/core.h" // The value for this FD must not conflict with uses inside Chromium. However, // mojo/nacl doesn't depend on any Chromium headers, so we can't use a #define
diff --git a/mojo/nacl/generator/mojo_syscall.cc.tmpl b/mojo/nacl/generator/mojo_syscall.cc.tmpl index 8ba76656..c3d835a1 100644 --- a/mojo/nacl/generator/mojo_syscall.cc.tmpl +++ b/mojo/nacl/generator/mojo_syscall.cc.tmpl
@@ -9,10 +9,10 @@ #include <stdio.h> #include "mojo/nacl/mojo_syscall_internal.h" -#include "mojo/public/c/system/core.h" #include "native_client/src/public/chrome_main.h" #include "native_client/src/public/nacl_app.h" #include "native_client/src/trusted/desc/nacl_desc_custom.h" +#include "third_party/mojo/src/mojo/public/c/system/core.h" namespace {
diff --git a/mojo/nacl/monacl_shell.cc b/mojo/nacl/monacl_shell.cc index 7922d9a..e838fa7 100644 --- a/mojo/nacl/monacl_shell.cc +++ b/mojo/nacl/monacl_shell.cc
@@ -4,9 +4,9 @@ #include <iostream> -#include "mojo/edk/embedder/embedder.h" -#include "mojo/edk/embedder/simple_platform_support.h" #include "mojo/nacl/monacl_sel_main.h" +#include "third_party/mojo/src/mojo/edk/embedder/embedder.h" +#include "third_party/mojo/src/mojo/edk/embedder/simple_platform_support.h" int main(int argc, char* argv[]) {
diff --git a/mojo/services/DEPS b/mojo/services/DEPS index 2bbe62d..a7ee2748 100644 --- a/mojo/services/DEPS +++ b/mojo/services/DEPS
@@ -3,6 +3,7 @@ "+mojo/common", "+mojo/public", "+jni", + "+third_party/mojo/src/mojo/public", # TODO(abarth) Instead of having the services depend on the shell, we # probably should create a layer below the services.
diff --git a/mojo/services/html_viewer/ax_provider_impl.h b/mojo/services/html_viewer/ax_provider_impl.h index 5f03e47..fba6be4 100644 --- a/mojo/services/html_viewer/ax_provider_impl.h +++ b/mojo/services/html_viewer/ax_provider_impl.h
@@ -5,8 +5,8 @@ #ifndef MOJO_SERVICES_HTML_VIEWER_AX_PROVIDER_IMPL_H_ #define MOJO_SERVICES_HTML_VIEWER_AX_PROVIDER_IMPL_H_ -#include "mojo/public/cpp/bindings/interface_impl.h" #include "mojo/services/accessibility/public/interfaces/accessibility.mojom.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_impl.h" namespace blink { class WebAXObject;
diff --git a/mojo/services/html_viewer/blink_basic_type_converters.cc b/mojo/services/html_viewer/blink_basic_type_converters.cc index cf6d610c..5324a7c3 100644 --- a/mojo/services/html_viewer/blink_basic_type_converters.cc +++ b/mojo/services/html_viewer/blink_basic_type_converters.cc
@@ -4,9 +4,9 @@ #include "mojo/services/html_viewer/blink_basic_type_converters.h" -#include "mojo/public/cpp/bindings/string.h" #include "third_party/WebKit/public/platform/WebRect.h" #include "third_party/WebKit/public/platform/WebString.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/string.h" using blink::WebRect; using blink::WebString;
diff --git a/mojo/services/html_viewer/blink_basic_type_converters.h b/mojo/services/html_viewer/blink_basic_type_converters.h index 7fc2f9b..65f0681 100644 --- a/mojo/services/html_viewer/blink_basic_type_converters.h +++ b/mojo/services/html_viewer/blink_basic_type_converters.h
@@ -5,11 +5,11 @@ #ifndef MOJO_SERVICES_HTML_VIEWER_BLINK_BASIC_TYPE_CONVERTERS_H_ #define MOJO_SERVICES_HTML_VIEWER_BLINK_BASIC_TYPE_CONVERTERS_H_ -#include "mojo/public/cpp/bindings/type_converter.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/type_converter.h" -#include "mojo/public/cpp/bindings/array.h" #include "mojo/services/geometry/public/interfaces/geometry.mojom.h" #include "third_party/WebKit/public/platform/WebVector.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/array.h" namespace blink { struct WebRect;
diff --git a/mojo/services/html_viewer/blink_url_request_type_converters.cc b/mojo/services/html_viewer/blink_url_request_type_converters.cc index 9428d92..85fd796 100644 --- a/mojo/services/html_viewer/blink_url_request_type_converters.cc +++ b/mojo/services/html_viewer/blink_url_request_type_converters.cc
@@ -5,9 +5,9 @@ #include "mojo/services/html_viewer/blink_url_request_type_converters.h" #include "base/strings/string_util.h" -#include "mojo/public/cpp/system/data_pipe.h" #include "third_party/WebKit/public/platform/WebHTTPHeaderVisitor.h" #include "third_party/WebKit/public/platform/WebURLRequest.h" +#include "third_party/mojo/src/mojo/public/cpp/system/data_pipe.h" namespace mojo { namespace {
diff --git a/mojo/services/html_viewer/html_document.cc b/mojo/services/html_viewer/html_document.cc index 6bd33a1..a6929581 100644 --- a/mojo/services/html_viewer/html_document.cc +++ b/mojo/services/html_viewer/html_document.cc
@@ -14,9 +14,6 @@ #include "base/thread_task_runner_handle.h" #include "media/blink/webencryptedmediaclient_impl.h" #include "media/cdm/default_cdm_factory.h" -#include "mojo/public/cpp/application/connect.h" -#include "mojo/public/cpp/system/data_pipe.h" -#include "mojo/public/interfaces/application/shell.mojom.h" #include "mojo/services/html_viewer/blink_input_events_type_converters.h" #include "mojo/services/html_viewer/blink_url_request_type_converters.h" #include "mojo/services/html_viewer/weblayertreeview_impl.h" @@ -37,6 +34,9 @@ #include "third_party/WebKit/public/web/WebScriptSource.h" #include "third_party/WebKit/public/web/WebSettings.h" #include "third_party/WebKit/public/web/WebView.h" +#include "third_party/mojo/src/mojo/public/cpp/application/connect.h" +#include "third_party/mojo/src/mojo/public/cpp/system/data_pipe.h" +#include "third_party/mojo/src/mojo/public/interfaces/application/shell.mojom.h" #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkColor.h" #include "third_party/skia/include/core/SkDevice.h"
diff --git a/mojo/services/html_viewer/html_document.h b/mojo/services/html_viewer/html_document.h index 42bf166d..40515b6b 100644 --- a/mojo/services/html_viewer/html_document.h +++ b/mojo/services/html_viewer/html_document.h
@@ -9,11 +9,6 @@ #include "base/callback.h" #include "base/macros.h" -#include "mojo/public/cpp/application/interface_factory.h" -#include "mojo/public/cpp/application/lazy_interface_ptr.h" -#include "mojo/public/cpp/application/service_provider_impl.h" -#include "mojo/public/cpp/bindings/interface_impl.h" -#include "mojo/public/interfaces/application/application.mojom.h" #include "mojo/services/content_handler/public/interfaces/content_handler.mojom.h" #include "mojo/services/html_viewer/ax_provider_impl.h" #include "mojo/services/navigation/public/interfaces/navigation.mojom.h" @@ -24,6 +19,11 @@ #include "third_party/WebKit/public/web/WebFrameClient.h" #include "third_party/WebKit/public/web/WebSandboxFlags.h" #include "third_party/WebKit/public/web/WebViewClient.h" +#include "third_party/mojo/src/mojo/public/cpp/application/interface_factory.h" +#include "third_party/mojo/src/mojo/public/cpp/application/lazy_interface_ptr.h" +#include "third_party/mojo/src/mojo/public/cpp/application/service_provider_impl.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_impl.h" +#include "third_party/mojo/src/mojo/public/interfaces/application/application.mojom.h" namespace base { class MessageLoopProxy;
diff --git a/mojo/services/html_viewer/html_viewer.cc b/mojo/services/html_viewer/html_viewer.cc index e5fd211..55d4c39 100644 --- a/mojo/services/html_viewer/html_viewer.cc +++ b/mojo/services/html_viewer/html_viewer.cc
@@ -10,12 +10,6 @@ #include "base/threading/thread.h" #include "gin/public/isolate_holder.h" #include "mojo/application/application_runner_chromium.h" -#include "mojo/public/c/system/main.h" -#include "mojo/public/cpp/application/application_connection.h" -#include "mojo/public/cpp/application/application_delegate.h" -#include "mojo/public/cpp/application/application_impl.h" -#include "mojo/public/cpp/application/connect.h" -#include "mojo/public/cpp/application/interface_factory_impl.h" #include "mojo/services/content_handler/public/interfaces/content_handler.mojom.h" #include "mojo/services/html_viewer/html_document.h" #include "mojo/services/html_viewer/mojo_blink_platform_impl.h" @@ -23,6 +17,12 @@ #include "mojo/services/network/public/interfaces/network_service.mojom.h" #include "third_party/WebKit/public/web/WebKit.h" #include "third_party/WebKit/public/web/WebRuntimeFeatures.h" +#include "third_party/mojo/src/mojo/public/c/system/main.h" +#include "third_party/mojo/src/mojo/public/cpp/application/application_connection.h" +#include "third_party/mojo/src/mojo/public/cpp/application/application_delegate.h" +#include "third_party/mojo/src/mojo/public/cpp/application/application_impl.h" +#include "third_party/mojo/src/mojo/public/cpp/application/connect.h" +#include "third_party/mojo/src/mojo/public/cpp/application/interface_factory_impl.h" #if !defined(COMPONENT_BUILD) #include "base/i18n/icu_util.h" @@ -52,8 +52,8 @@ // media::Renderer implementation. const char kEnableMojoMediaRenderer[] = "enable-mojo-media-renderer"; -// Enables support for Encrypted Media Extensions (e.g. MediaKeys). -const char kEnableEncryptedMedia[] = "enable-encrypted-media"; +// Disables support for (unprefixed) Encrypted Media Extensions. +const char kDisableEncryptedMedia[] = "disable-encrypted-media"; class HTMLViewer; @@ -184,8 +184,8 @@ bool enable_mojo_media_renderer = command_line->HasSwitch(kEnableMojoMediaRenderer); - if (command_line->HasSwitch(kEnableEncryptedMedia)) - blink::WebRuntimeFeatures::enableEncryptedMedia(true); + if (command_line->HasSwitch(kDisableEncryptedMedia)) + blink::WebRuntimeFeatures::enableEncryptedMedia(false); compositor_thread_.Start(); web_media_player_factory_.reset(new WebMediaPlayerFactory(
diff --git a/mojo/services/html_viewer/mojo_blink_platform_impl.cc b/mojo/services/html_viewer/mojo_blink_platform_impl.cc index 40419b1..6b27ab16 100644 --- a/mojo/services/html_viewer/mojo_blink_platform_impl.cc +++ b/mojo/services/html_viewer/mojo_blink_platform_impl.cc
@@ -4,11 +4,11 @@ #include "mojo/services/html_viewer/mojo_blink_platform_impl.h" -#include "mojo/public/cpp/application/application_impl.h" #include "mojo/services/html_viewer/webclipboard_impl.h" #include "mojo/services/html_viewer/webcookiejar_impl.h" #include "mojo/services/html_viewer/websockethandle_impl.h" #include "mojo/services/html_viewer/weburlloader_impl.h" +#include "third_party/mojo/src/mojo/public/cpp/application/application_impl.h" namespace html_viewer {
diff --git a/mojo/services/html_viewer/webmediaplayer_factory.cc b/mojo/services/html_viewer/webmediaplayer_factory.cc index df113bf1..e3c925e 100644 --- a/mojo/services/html_viewer/webmediaplayer_factory.cc +++ b/mojo/services/html_viewer/webmediaplayer_factory.cc
@@ -21,8 +21,8 @@ #include "media/filters/gpu_video_accelerator_factories.h" #include "media/mojo/interfaces/media_renderer.mojom.h" #include "media/mojo/services/mojo_renderer_factory.h" -#include "mojo/public/cpp/application/connect.h" -#include "mojo/public/interfaces/application/shell.mojom.h" +#include "third_party/mojo/src/mojo/public/cpp/application/connect.h" +#include "third_party/mojo/src/mojo/public/interfaces/application/shell.mojom.h" using mojo::ServiceProviderPtr;
diff --git a/mojo/services/network/BUILD.gn b/mojo/services/network/BUILD.gn index 477005f..6aa4b98 100644 --- a/mojo/services/network/BUILD.gn +++ b/mojo/services/network/BUILD.gn
@@ -2,6 +2,9 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +# TODO(ppi): Switch this file back to using absolute paths to refer to the Mojo +# SDK once it is no longer being used to build the network service impl in +# Mojo. import("../mojo_sdk_root.gni") import("$mojo_sdk_root/mojo/public/mojo_application.gni")
diff --git a/mojo/services/network/net_address_type_converters.h b/mojo/services/network/net_address_type_converters.h index f9999087..a1af10e 100644 --- a/mojo/services/network/net_address_type_converters.h +++ b/mojo/services/network/net_address_type_converters.h
@@ -5,9 +5,9 @@ #ifndef MOJO_SERVICES_NETWORK_NET_ADDRESS_TYPE_CONVERTERS_H_ #define MOJO_SERVICES_NETWORK_NET_ADDRESS_TYPE_CONVERTERS_H_ -#include "mojo/public/cpp/bindings/type_converter.h" #include "mojo/services/network/public/interfaces/net_address.mojom.h" #include "net/base/ip_endpoint.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/type_converter.h" namespace mojo {
diff --git a/mojo/services/network/network_service.cc b/mojo/services/network/network_service.cc index 0f604fbd..8079ba1 100644 --- a/mojo/services/network/network_service.cc +++ b/mojo/services/network/network_service.cc
@@ -9,13 +9,13 @@ #include "base/message_loop/message_loop.h" #include "base/path_service.h" #include "mojo/application/application_runner_chromium.h" -#include "mojo/public/c/system/main.h" -#include "mojo/public/cpp/application/application_connection.h" -#include "mojo/public/cpp/application/application_delegate.h" -#include "mojo/public/cpp/application/interface_factory.h" -#include "mojo/public/cpp/bindings/interface_ptr.h" #include "mojo/services/network/network_context.h" #include "mojo/services/network/network_service_impl.h" +#include "third_party/mojo/src/mojo/public/c/system/main.h" +#include "third_party/mojo/src/mojo/public/cpp/application/application_connection.h" +#include "third_party/mojo/src/mojo/public/cpp/application/application_delegate.h" +#include "third_party/mojo/src/mojo/public/cpp/application/interface_factory.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_ptr.h" class NetworkServiceDelegate : public mojo::ApplicationDelegate,
diff --git a/mojo/services/network/network_service_impl.cc b/mojo/services/network/network_service_impl.cc index 708208a..64eb337 100644 --- a/mojo/services/network/network_service_impl.cc +++ b/mojo/services/network/network_service_impl.cc
@@ -4,13 +4,13 @@ #include "mojo/services/network/network_service_impl.h" -#include "mojo/public/cpp/application/application_connection.h" #include "mojo/services/network/cookie_store_impl.h" #include "mojo/services/network/net_adapters.h" #include "mojo/services/network/tcp_bound_socket_impl.h" #include "mojo/services/network/udp_socket_impl.h" #include "mojo/services/network/url_loader_impl.h" #include "mojo/services/network/web_socket_impl.h" +#include "third_party/mojo/src/mojo/public/cpp/application/application_connection.h" namespace mojo {
diff --git a/mojo/services/network/network_service_impl.h b/mojo/services/network/network_service_impl.h index c3bebe41..9d4baae1 100644 --- a/mojo/services/network/network_service_impl.h +++ b/mojo/services/network/network_service_impl.h
@@ -6,8 +6,8 @@ #define MOJO_SERVICES_NETWORK_NETWORK_SERVICE_IMPL_H_ #include "base/compiler_specific.h" -#include "mojo/public/cpp/bindings/interface_impl.h" #include "mojo/services/network/public/interfaces/network_service.mojom.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_impl.h" #include "url/gurl.h" namespace mojo {
diff --git a/mojo/services/network/public/DEPS b/mojo/services/network/public/DEPS index ae35a92..b8b14d2 100644 --- a/mojo/services/network/public/DEPS +++ b/mojo/services/network/public/DEPS
@@ -6,6 +6,6 @@ "-testing", "!base", "!mojo/common", - "+mojo/public", "+mojo/services/network/public", + "+third_party/mojo/src/mojo/public", ]
diff --git a/mojo/services/network/public/cpp/udp_socket_wrapper.cc b/mojo/services/network/public/cpp/udp_socket_wrapper.cc index 8d8b7ea..4510c273 100644 --- a/mojo/services/network/public/cpp/udp_socket_wrapper.cc +++ b/mojo/services/network/public/cpp/udp_socket_wrapper.cc
@@ -6,7 +6,7 @@ #include <assert.h> -#include "mojo/public/cpp/environment/logging.h" +#include "third_party/mojo/src/mojo/public/cpp/environment/logging.h" namespace mojo { namespace {
diff --git a/mojo/services/network/public/cpp/web_socket_read_queue.h b/mojo/services/network/public/cpp/web_socket_read_queue.h index 905f94e..2731510 100644 --- a/mojo/services/network/public/cpp/web_socket_read_queue.h +++ b/mojo/services/network/public/cpp/web_socket_read_queue.h
@@ -8,7 +8,7 @@ #include "base/callback.h" #include "base/memory/scoped_vector.h" #include "mojo/common/handle_watcher.h" -#include "mojo/public/cpp/system/data_pipe.h" +#include "third_party/mojo/src/mojo/public/cpp/system/data_pipe.h" namespace mojo {
diff --git a/mojo/services/network/public/cpp/web_socket_write_queue.h b/mojo/services/network/public/cpp/web_socket_write_queue.h index e683be4..b2c48fc 100644 --- a/mojo/services/network/public/cpp/web_socket_write_queue.h +++ b/mojo/services/network/public/cpp/web_socket_write_queue.h
@@ -8,7 +8,7 @@ #include "base/callback.h" #include "base/memory/scoped_vector.h" #include "mojo/common/handle_watcher.h" -#include "mojo/public/cpp/system/data_pipe.h" +#include "third_party/mojo/src/mojo/public/cpp/system/data_pipe.h" namespace mojo {
diff --git a/mojo/services/network/tcp_bound_socket_impl.h b/mojo/services/network/tcp_bound_socket_impl.h index bb2fe67..e5e1b6c2 100644 --- a/mojo/services/network/tcp_bound_socket_impl.h +++ b/mojo/services/network/tcp_bound_socket_impl.h
@@ -6,9 +6,9 @@ #define MOJO_SERVICES_NETWORK_TCP_BOUND_SOCKET_H_ #include "base/memory/scoped_ptr.h" -#include "mojo/public/cpp/bindings/interface_impl.h" #include "mojo/services/network/public/interfaces/tcp_bound_socket.mojom.h" #include "net/socket/tcp_socket.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_impl.h" namespace mojo {
diff --git a/mojo/services/network/tcp_connected_socket_impl.h b/mojo/services/network/tcp_connected_socket_impl.h index 041f858..0eb95e2 100644 --- a/mojo/services/network/tcp_connected_socket_impl.h +++ b/mojo/services/network/tcp_connected_socket_impl.h
@@ -8,9 +8,9 @@ #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "mojo/common/handle_watcher.h" -#include "mojo/public/cpp/bindings/interface_impl.h" #include "mojo/services/network/public/interfaces/tcp_connected_socket.mojom.h" #include "net/socket/tcp_socket.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_impl.h" namespace mojo {
diff --git a/mojo/services/network/tcp_server_socket_impl.h b/mojo/services/network/tcp_server_socket_impl.h index 00099515..0039f8d 100644 --- a/mojo/services/network/tcp_server_socket_impl.h +++ b/mojo/services/network/tcp_server_socket_impl.h
@@ -6,10 +6,10 @@ #define MOJO_SERVICES_NETWORK_TCP_SERVER_SOCKET_H_ #include "base/memory/scoped_ptr.h" -#include "mojo/public/cpp/bindings/interface_impl.h" #include "mojo/services/network/public/interfaces/tcp_server_socket.mojom.h" #include "net/base/ip_endpoint.h" #include "net/socket/tcp_socket.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_impl.h" namespace mojo {
diff --git a/mojo/services/network/udp_socket_impl.h b/mojo/services/network/udp_socket_impl.h index f5d3f8225..eb63d93 100644 --- a/mojo/services/network/udp_socket_impl.h +++ b/mojo/services/network/udp_socket_impl.h
@@ -9,10 +9,10 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "mojo/public/cpp/bindings/interface_impl.h" #include "mojo/services/network/public/interfaces/udp_socket.mojom.h" #include "net/base/ip_endpoint.h" #include "net/udp/udp_socket.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_impl.h" namespace net { class IOBuffer;
diff --git a/mojo/services/network/udp_socket_unittest.cc b/mojo/services/network/udp_socket_unittest.cc index ae6f512..ddb9d93d 100644 --- a/mojo/services/network/udp_socket_unittest.cc +++ b/mojo/services/network/udp_socket_unittest.cc
@@ -5,13 +5,13 @@ #include "base/at_exit.h" #include "base/macros.h" #include "base/memory/scoped_ptr.h" -#include "mojo/public/cpp/bindings/callback.h" #include "mojo/services/network/public/cpp/udp_socket_wrapper.h" #include "mojo/services/network/public/interfaces/network_service.mojom.h" #include "mojo/services/network/public/interfaces/udp_socket.mojom.h" #include "mojo/shell/shell_test_helper.h" #include "net/base/net_errors.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/callback.h" #include "url/gurl.h" namespace mojo {
diff --git a/mojo/services/network/upload_network_service.py b/mojo/services/network/upload_network_service.py index 510494d..ac7b619a 100755 --- a/mojo/services/network/upload_network_service.py +++ b/mojo/services/network/upload_network_service.py
@@ -12,6 +12,10 @@ import time import zipfile +if not sys.platform.startswith("linux"): + print "Only support linux for now" + sys.exit(1) + root_path = os.path.realpath( os.path.join( os.path.dirname( @@ -22,13 +26,6 @@ version = subprocess.check_output(["git", "rev-parse", "HEAD"], cwd=root_path) version = version.strip() -if not sys.platform.startswith("linux"): - print "Only support linux for now" - sys.exit(1) - -platform = "linux-x64" # TODO: Parameterize -binary_dest = "gs://mojo/network/" + version + "/" + platform + ".zip" - find_depot_tools_path = os.path.join(root_path, "tools", "find_depot_tools.py") find_depot_tools = imp.load_source("find_depot_tools", find_depot_tools_path) @@ -43,30 +40,61 @@ subprocess.check_call([gsutil_exe, "cp", source, dest]) -def upload_binary(binary_path, dry_run): +def upload_mojoms(dry_run): + absolute_mojom_directory_path = os.path.join( + os.path.dirname(os.path.realpath(__file__)), + "public", + "interfaces") + dest = "gs://mojo/network/" + version + "/" + "mojoms.zip" + with tempfile.NamedTemporaryFile() as mojom_zip_file: + with zipfile.ZipFile(mojom_zip_file, 'w') as z: + for root, _, files in os.walk(absolute_mojom_directory_path): + for filename in files: + absolute_file_path = os.path.join(root, filename) + relative_file_path = os.path.relpath(absolute_file_path, root) + z.write(absolute_file_path, relative_file_path) + gsutil_cp(mojom_zip_file.name, dest, dry_run) + + +def upload_binary(binary_path, platform, dry_run): absolute_binary_path = os.path.join(root_path, binary_path) + binary_dest = "gs://mojo/network/" + version + "/" + platform + ".zip" with tempfile.NamedTemporaryFile() as binary_zip_file: with zipfile.ZipFile(binary_zip_file, 'w') as z: with open(absolute_binary_path) as service_binary: - zipinfo = zipfile.ZipInfo("libnetwork_service.so") + zipinfo = zipfile.ZipInfo("network_service.mojo") zipinfo.external_attr = 0o777 << 16 zipinfo.compress_type = zipfile.ZIP_DEFLATED zipinfo.date_time = time.gmtime(os.path.getmtime(absolute_binary_path)) z.writestr(zipinfo, service_binary.read()) - gsutil_cp(binary_zip_file.name, binary_dest, dry_run) + gsutil_cp(binary_zip_file.name, binary_dest, dry_run) def main(): parser = argparse.ArgumentParser( - description="Upload network service binary to Google storage") + description="Upload network service mojoms and binaries to Google " + + "storage") parser.add_argument("-n", "--dry-run", action="store_true", help="Dry run") parser.add_argument( - "binary_path", - help="Path to network service binary relative to the repo root, e.g. " + - "out/Release/libnetwork_service.so") + "--linux-x64-binary-path", + help="Path to the linux-x64 network service binary relative to the " + + "repo root, e.g. out/Release/network_service.mojo") + parser.add_argument( + "--android-arm-binary-path", + help="Path to the android-arm network service binary relative to the " + + "repo root, e.g. out/android_Release/network_service.mojo") + args = parser.parse_args() - upload_binary(args.binary_path, args.dry_run) - print "Uploaded artifacts for %s %s" % (version, "linux-x64") + upload_mojoms(args.dry_run) + if args.linux_x64_binary_path: + upload_binary(args.linux_x64_binary_path, "linux-x64", args.dry_run) + if args.android_arm_binary_path: + upload_binary(args.android_arm_binary_path, "android-arm", args.dry_run) + + if not args.dry_run: + print "Uploaded artifacts for version %s" % (version, ) + else: + print "No artifacts uploaded (dry run)" return 0 if __name__ == '__main__':
diff --git a/mojo/services/network/url_loader_impl.h b/mojo/services/network/url_loader_impl.h index 40d087d..8c259bd 100644 --- a/mojo/services/network/url_loader_impl.h +++ b/mojo/services/network/url_loader_impl.h
@@ -8,12 +8,12 @@ #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "mojo/common/handle_watcher.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "mojo/public/cpp/bindings/error_handler.h" -#include "mojo/public/cpp/bindings/interface_impl.h" #include "mojo/services/network/public/interfaces/url_loader.mojom.h" #include "net/base/net_errors.h" #include "net/url_request/url_request.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/binding.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/error_handler.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_impl.h" namespace mojo {
diff --git a/mojo/services/network/web_socket_impl.h b/mojo/services/network/web_socket_impl.h index 457f4ff..bb41104 100644 --- a/mojo/services/network/web_socket_impl.h +++ b/mojo/services/network/web_socket_impl.h
@@ -6,8 +6,8 @@ #define MOJO_SERVICES_NETWORK_WEB_SOCKET_IMPL_H_ #include "base/memory/scoped_ptr.h" -#include "mojo/public/cpp/bindings/interface_impl.h" #include "mojo/services/network/public/interfaces/web_socket.mojom.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_impl.h" namespace net { class WebSocketChannel;
diff --git a/native_client_sdk/doc_generated/cds2014/cpp.html b/native_client_sdk/doc_generated/cds2014/cpp.html index 6286b27..a676895 100644 --- a/native_client_sdk/doc_generated/cds2014/cpp.html +++ b/native_client_sdk/doc_generated/cds2014/cpp.html
@@ -158,7 +158,7 @@ you with a zip file containing a starting point.</p> <p>Download the codelab:</p> <pre class="prettyprint"> -curl https://nacltools.storage.googleapis.com/cds2014/cds2014_cpp.zip -O +curl http://nacltools.storage.googleapis.com/cds2014/cds2014_cpp.zip -O </pre> <p>Unzip it:</p> <pre class="prettyprint">
diff --git a/native_client_sdk/src/build_tools/sdk_tools/third_party/fancy_urllib/README.chromium b/native_client_sdk/src/build_tools/sdk_tools/third_party/fancy_urllib/README.chromium index fbbeb3b..e6016b3 100644 --- a/native_client_sdk/src/build_tools/sdk_tools/third_party/fancy_urllib/README.chromium +++ b/native_client_sdk/src/build_tools/sdk_tools/third_party/fancy_urllib/README.chromium
@@ -24,3 +24,8 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + +Local Modifications: +- Python 2.7.9 adds an additional parameter to urllib2.HTTPSHandler.do_open. I + modified FancyHTTPSHandler.do_open to take this parameter and forward it to + the super function.
diff --git a/native_client_sdk/src/build_tools/sdk_tools/third_party/fancy_urllib/__init__.py b/native_client_sdk/src/build_tools/sdk_tools/third_party/fancy_urllib/__init__.py index d4da0dd..dfbad4d 100644 --- a/native_client_sdk/src/build_tools/sdk_tools/third_party/fancy_urllib/__init__.py +++ b/native_client_sdk/src/build_tools/sdk_tools/third_party/fancy_urllib/__init__.py
@@ -329,7 +329,7 @@ class FancyHTTPSHandler(urllib2.HTTPSHandler): """An HTTPSHandler that works with CONNECT-enabled proxies.""" - def do_open(self, http_class, req): + def do_open(self, http_class, req, **kwargs): # Intentionally very specific so as to opt for false negatives # rather than false positives. try: @@ -339,7 +339,8 @@ req._key_file, req._cert_file, req._ca_certs), - req) + req, + **kwargs) except urllib2.URLError, url_error: try: import ssl
diff --git a/native_client_sdk/src/build_tools/tests/parse_dsc_test.py b/native_client_sdk/src/build_tools/tests/parse_dsc_test.py index 05a86325..77f96b8 100755 --- a/native_client_sdk/src/build_tools/tests/parse_dsc_test.py +++ b/native_client_sdk/src/build_tools/tests/parse_dsc_test.py
@@ -81,7 +81,7 @@ testdesc['TOOLS'] = 'newlib' self._validate(testdesc, 'Key TOOLS expects LIST not STR.') -# TODO(noelallen): Add test which generates a real make and runs it. +# TODO(bradnelson): Add test which generates a real make and runs it. if __name__ == '__main__': unittest.main()
diff --git a/native_client_sdk/src/doc/cds2014/cpp.rst b/native_client_sdk/src/doc/cds2014/cpp.rst index 067e74e..881bb56 100644 --- a/native_client_sdk/src/doc/cds2014/cpp.rst +++ b/native_client_sdk/src/doc/cds2014/cpp.rst
@@ -19,7 +19,7 @@ Download the codelab:: - curl https://nacltools.storage.googleapis.com/cds2014/cds2014_cpp.zip -O + curl http://nacltools.storage.googleapis.com/cds2014/cds2014_cpp.zip -O Unzip it::
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc b/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc index d9d9567..c974f6b 100644 --- a/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc +++ b/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc
@@ -972,7 +972,7 @@ return FutimensInternal(node, times); } -// TODO(noelallen): Needs implementation. +// TODO(bradnelson): Needs implementation. int KernelProxy::link(const char* oldpath, const char* newpath) { LOG_TRACE("link is not implemented."); errno = EINVAL;
diff --git a/native_client_sdk/src/libraries/nacl_io/node.h b/native_client_sdk/src/libraries/nacl_io/node.h index 54e6605..f1ebdc3c 100644 --- a/native_client_sdk/src/libraries/nacl_io/node.h +++ b/native_client_sdk/src/libraries/nacl_io/node.h
@@ -140,7 +140,7 @@ sdk_util::SimpleLock node_lock_; // We use a pointer directly to avoid cycles in the ref count. - // TODO(noelallen) We should change this so it's unnecessary for the node + // TODO(bradnelson) We should change this so it's unnecessary for the node // to track it's parent. When a node is unlinked, the filesystem should do // any cleanup it needs. Filesystem* filesystem_;
diff --git a/native_client_sdk/src/libraries/nacl_io/socket/socket_node.cc b/native_client_sdk/src/libraries/nacl_io/socket/socket_node.cc index 95cc4f3..4eaf6ac6 100644 --- a/native_client_sdk/src/libraries/nacl_io/socket/socket_node.cc +++ b/native_client_sdk/src/libraries/nacl_io/socket/socket_node.cc
@@ -364,7 +364,7 @@ if ((flags & MSG_DONTWAIT) || !attr.IsBlocking()) ms = 0; - // TODO(noelallen) BUG=295177 + // TODO(bradnelson) BUG=295177 // For UDP we should support filtering packets when using connect EventListenerLock wait(GetEventEmitter()); Error err = wait.WaitOnEvent(POLLIN, ms);
diff --git a/native_client_sdk/src/tests/nacl_io_test/event_test.cc b/native_client_sdk/src/tests/nacl_io_test/event_test.cc index 8084df07..f85f9e2 100644 --- a/native_client_sdk/src/tests/nacl_io_test/event_test.cc +++ b/native_client_sdk/src/tests/nacl_io_test/event_test.cc
@@ -290,7 +290,7 @@ SetFDs(fds, 2); ASSERT_EQ(2, kp->poll(pollfds, 2, 0)); - // TODO(noelallen) fix poll based on open mode + // TODO(bradnelson) fix poll based on open mode // EXPECT_EQ(0, pollfds[0].revents); // Bug 291018 ASSERT_EQ(POLLOUT, pollfds[1].revents); @@ -325,7 +325,7 @@ ASSERT_EQ(2, kp->select(fds[1] + 1, &rd_set, &wr_set, &ex_set, &tv)); EXPECT_EQ(0, FD_ISSET(fds[0], &rd_set)); EXPECT_EQ(0, FD_ISSET(fds[1], &rd_set)); - // TODO(noelallen) fix poll based on open mode + // TODO(bradnelson) fix poll based on open mode // EXPECT_EQ(0, FD_ISSET(fds[0], &wr_set)); // Bug 291018 EXPECT_NE(0, FD_ISSET(fds[1], &wr_set));
diff --git a/native_client_sdk/src/tools/lib/get_shared_deps.py b/native_client_sdk/src/tools/lib/get_shared_deps.py index b7b433f..7a355ca 100644 --- a/native_client_sdk/src/tools/lib/get_shared_deps.py +++ b/native_client_sdk/src/tools/lib/get_shared_deps.py
@@ -211,7 +211,7 @@ # the SONAME is actually libc.so. If we pass glibc's libc.so to objdump # if fails to parse it, os this filters out libc.so expept for within # the bionic toolchain. - # TODO(noelallen): Remove this once the SONAME in bionic is made to be + # TODO(bradnelson): Remove this once the SONAME in bionic is made to be # unique in the same it is under glibc: # https://code.google.com/p/nativeclient/issues/detail?id=3833 rel_dirname = os.path.relpath(dirname, SDK_DIR)
diff --git a/net/BUILD.gn b/net/BUILD.gn index f235c301..52444d59 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn
@@ -1262,6 +1262,7 @@ "websockets/websocket_deflate_stream_test.cc", "websockets/websocket_deflater_test.cc", "websockets/websocket_errors_test.cc", + "websockets/websocket_end_to_end_test.cc", "websockets/websocket_extension_parser_test.cc", "websockets/websocket_frame_parser_test.cc", "websockets/websocket_frame_test.cc",
diff --git a/net/base/address_list_unittest.cc b/net/base/address_list_unittest.cc index e559788..4f70b67 100644 --- a/net/base/address_list_unittest.cc +++ b/net/base/address_list_unittest.cc
@@ -13,7 +13,7 @@ namespace net { namespace { -static const char* kCanonicalHostname = "canonical.bar.com"; +const char kCanonicalHostname[] = "canonical.bar.com"; TEST(AddressListTest, Canonical) { // Create an addrinfo with a canonical name.
diff --git a/net/base/bandwidth_metrics.h b/net/base/bandwidth_metrics.h index e5f2646..679d65a6 100644 --- a/net/base/bandwidth_metrics.h +++ b/net/base/bandwidth_metrics.h
@@ -70,7 +70,7 @@ // If we're the only stream, we've finished some idle time. Record a new // timestamp to indicate the start of data flow. if (++num_streams_in_progress_ == 1) { - last_start_ = base::TimeTicks::HighResNow(); + last_start_ = base::TimeTicks::Now(); bytes_since_last_start_ = 0; } } @@ -86,7 +86,7 @@ if (bytes_since_last_start_ < kRecordSizeThreshold) return; - base::TimeDelta delta = base::TimeTicks::HighResNow() - last_start_; + base::TimeDelta delta = base::TimeTicks::Now() - last_start_; double ms = delta.InMillisecondsF(); if (ms > 0.0) { double kbps = static_cast<double>(bytes_since_last_start_) * 8 / ms;
diff --git a/net/base/mime_sniffer.cc b/net/base/mime_sniffer.cc index ad4212dc28..0d1f1169 100644 --- a/net/base/mime_sniffer.cc +++ b/net/base/mime_sniffer.cc
@@ -110,11 +110,11 @@ static const size_t kBytesRequiredForMagic = 42; struct MagicNumber { - const char* mime_type; - const char* magic; + const char* const mime_type; + const char* const magic; size_t magic_len; bool is_string; - const char* mask; // if set, must have same length as |magic| + const char* const mask; // if set, must have same length as |magic| }; #define MAGIC_NUMBER(mime_type, magic) \ @@ -209,7 +209,7 @@ struct OfficeExtensionType { OfficeDocType doc_type; - const char* extension; + const char* const extension; size_t extension_len; }; @@ -724,7 +724,7 @@ static bool IsUnknownMimeType(const std::string& mime_type) { // TODO(tc): Maybe reuse some code in net/http/http_response_headers.* here. // If we do, please be careful not to alter the semantics at all. - static const char* kUnknownMimeTypes[] = { + static const char* const kUnknownMimeTypes[] = { // Empty mime types are as unknown as they get. "", // The unknown/unknown type is popular and uninformative @@ -819,7 +819,7 @@ return false; } - static const char* kSniffableTypes[] = { + static const char* const kSniffableTypes[] = { // Many web servers are misconfigured to send text/plain for many // different types of content. "text/plain",
diff --git a/net/base/mime_util.cc b/net/base/mime_util.cc index d1b67d58..a7fe9f3e 100644 --- a/net/base/mime_util.cc +++ b/net/base/mime_util.cc
@@ -174,8 +174,8 @@ LAZY_INSTANCE_INITIALIZER; struct MimeInfo { - const char* mime_type; - const char* extensions; // comma separated list + const char* const mime_type; + const char* const extensions; // comma separated list }; static const MimeInfo primary_mappings[] = { @@ -385,7 +385,7 @@ // Dictionary of cryptographic file mime types. struct CertificateMimeTypeInfo { - const char* mime_type; + const char* const mime_type; CertificateMimeType cert_type; }; @@ -498,8 +498,8 @@ #endif struct MediaFormatStrict { - const char* mime_type; - const char* codecs_list; + const char* const mime_type; + const char* const codecs_list; }; // Following is the list of RFC 6381 compliant codecs: @@ -799,7 +799,7 @@ } // See http://www.iana.org/assignments/media-types/media-types.xhtml -static const char* legal_top_level_types[] = { +static const char* const legal_top_level_types[] = { "application", "audio", "example", @@ -1223,7 +1223,7 @@ }; struct StandardType { - const char* leading_mime_type; + const char* const leading_mime_type; const char* const* standard_types; size_t standard_types_len; };
diff --git a/net/base/mime_util_unittest.cc b/net/base/mime_util_unittest.cc index a3d9516e..a28c8b69 100644 --- a/net/base/mime_util_unittest.cc +++ b/net/base/mime_util_unittest.cc
@@ -17,7 +17,7 @@ TEST(MimeUtilTest, ExtensionTest) { const struct { const base::FilePath::CharType* extension; - const char* mime_type; + const char* const mime_type; bool valid; } tests[] = { { FILE_PATH_LITERAL("png"), "image/png", true }, @@ -44,7 +44,7 @@ TEST(MimeUtilTest, FileTest) { const struct { const base::FilePath::CharType* file_path; - const char* mime_type; + const char* const mime_type; bool valid; } tests[] = { { FILE_PATH_LITERAL("c:\\foo\\bar.css"), "text/css", true }, @@ -258,9 +258,9 @@ // results' length to 2. TEST(MimeUtilTest, ParseCodecString) { const struct { - const char* original; + const char* const original; size_t expected_size; - const char* results[2]; + const char* const results[2]; } tests[] = { { "\"bogus\"", 1, { "bogus" } }, { "0", 1, { "0" } }, @@ -365,9 +365,9 @@ TEST(MimeUtilTest, TestGetExtensionsForMimeType) { const struct { - const char* mime_type; + const char* const mime_type; size_t min_expected_size; - const char* contained_result; + const char* const contained_result; } tests[] = { { "text/plain", 2, "txt" }, { "*", 0, NULL }, @@ -427,12 +427,13 @@ } TEST(MimeUtilTest, TestAddMultipartValueForUpload) { - const char* ref_output = "--boundary\r\nContent-Disposition: form-data;" - " name=\"value name\"\r\nContent-Type: content type" - "\r\n\r\nvalue\r\n" - "--boundary\r\nContent-Disposition: form-data;" - " name=\"value name\"\r\n\r\nvalue\r\n" - "--boundary--\r\n"; + const char ref_output[] = + "--boundary\r\nContent-Disposition: form-data;" + " name=\"value name\"\r\nContent-Type: content type" + "\r\n\r\nvalue\r\n" + "--boundary\r\nContent-Disposition: form-data;" + " name=\"value name\"\r\n\r\nvalue\r\n" + "--boundary--\r\n"; std::string post_data; AddMultipartValueForUpload("value name", "value", "boundary", "content type", &post_data);
diff --git a/net/base/net_string_util_icu_alternatives_android.cc b/net/base/net_string_util_icu_alternatives_android.cc index ca0e7f0..f4ef1ef 100644 --- a/net/base/net_string_util_icu_alternatives_android.cc +++ b/net/base/net_string_util_icu_alternatives_android.cc
@@ -66,7 +66,7 @@ } // namespace -const char* const kCharsetLatin1 = "ISO-8859-1"; +const char kCharsetLatin1[] = "ISO-8859-1"; bool ConvertToUtf8(const std::string& text, const char* charset, std::string* output) {
diff --git a/net/base/net_util_icu.cc b/net/base/net_util_icu.cc index 8526edaf..176826c4 100644 --- a/net/base/net_util_icu.cc +++ b/net/base/net_util_icu.cc
@@ -670,9 +670,9 @@ // Special handling for view-source:. Don't use content::kViewSourceScheme // because this library shouldn't depend on chrome. - const char* const kViewSource = "view-source"; + const char kViewSource[] = "view-source"; // Reject "view-source:view-source:..." to avoid deep recursion. - const char* const kViewSourceTwice = "view-source:view-source:"; + const char kViewSourceTwice[] = "view-source:view-source:"; if (url.SchemeIs(kViewSource) && !StartsWithASCII(url.possibly_invalid_spec(), kViewSourceTwice, false)) { return FormatViewSourceUrl(url, languages, format_types,
diff --git a/net/base/net_util_icu_unittest.cc b/net/base/net_util_icu_unittest.cc index d92b9d1..9af0e2a 100644 --- a/net/base/net_util_icu_unittest.cc +++ b/net/base/net_util_icu_unittest.cc
@@ -22,9 +22,9 @@ namespace { -static const size_t kNpos = base::string16::npos; +const size_t kNpos = base::string16::npos; -const char* kLanguages[] = { +const char* const kLanguages[] = { "", "en", "zh-CN", "ja", "ko", "he", "ar", "ru", "el", "fr", "de", "pt", "sv", "th", "hi", @@ -33,7 +33,7 @@ }; struct IDNTestCase { - const char* input; + const char* const input; const wchar_t* unicode_output; const bool unicode_allowed[arraysize(kLanguages)]; }; @@ -354,9 +354,9 @@ }; struct UrlTestData { - const char* description; - const char* input; - const char* languages; + const char* const description; + const char* const input; + const char* const languages; FormatUrlTypes format_types; UnescapeRule::Type escape_rules; const wchar_t* output; // Use |wchar_t| to handle Unicode constants easily. @@ -455,11 +455,11 @@ struct GetDirectoryListingEntryCase { const wchar_t* name; - const char* raw_bytes; + const char* const raw_bytes; bool is_dir; int64 filesize; base::Time time; - const char* expected; + const char* const expected; }; } // namespace @@ -930,7 +930,7 @@ TEST(NetUtilTest, FormatUrlRoundTripQueryEscaped) { // A full list of characters which FormatURL should unescape and GURL should // not escape again, when they appear in a query string. - const char* kUnescapedCharacters = + const char kUnescapedCharacters[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_~"; for (unsigned char test_char = 0; test_char < 128; ++test_char) { std::string original_url("http://www.google.com/?");
diff --git a/net/base/net_util_unittest.cc b/net/base/net_util_unittest.cc index cb9ec1ffc..60fae68 100644 --- a/net/base/net_util_unittest.cc +++ b/net/base/net_util_unittest.cc
@@ -61,8 +61,8 @@ namespace { struct HeaderCase { - const char* header_name; - const char* expected; + const char* const header_name; + const char* const expected; }; // Fills in sockaddr for the given 32-bit address (IPv4.) @@ -154,9 +154,9 @@ TEST(NetUtilTest, GetIdentityFromURL) { struct { - const char* input_url; - const char* expected_username; - const char* expected_password; + const char* const input_url; + const char* const expected_username; + const char* const expected_password; } tests[] = { { "http://username:password@google.com", @@ -224,7 +224,7 @@ } // Just a bunch of fake headers. -const char* google_headers = +const char google_headers[] = "HTTP/1.1 200 OK\n" "Content-TYPE: text/html; charset=utf-8\n" "Content-disposition: attachment; filename=\"download.pdf\"\n" @@ -271,7 +271,7 @@ TEST(NetUtilTest, CompliantHost) { struct CompliantHostCase { - const char* host; + const char* const host; bool expected_output; }; @@ -308,9 +308,9 @@ TEST(NetUtilTest, ParseHostAndPort) { const struct { - const char* input; + const char* const input; bool success; - const char* expected_host; + const char* const expected_host; int expected_port; } tests[] = { // Valid inputs: @@ -367,7 +367,7 @@ TEST(NetUtilTest, GetHostAndPort) { const struct { GURL url; - const char* expected_host_and_port; + const char* const expected_host_and_port; } tests[] = { { GURL("http://www.foo.com/x"), "www.foo.com:80"}, { GURL("http://www.foo.com:21/x"), "www.foo.com:21"}, @@ -385,7 +385,7 @@ TEST(NetUtilTest, GetHostAndOptionalPort) { const struct { GURL url; - const char* expected_host_and_port; + const char* const expected_host_and_port; } tests[] = { { GURL("http://www.foo.com/x"), "www.foo.com"}, { GURL("http://www.foo.com:21/x"), "www.foo.com:21"}, @@ -427,7 +427,7 @@ TEST(NetUtilTest, NetAddressToString_IPv4) { const struct { uint8 addr[4]; - const char* result; + const char* const result; } tests[] = { {{0, 0, 0, 0}, "0.0.0.0"}, {{127, 0, 0, 1}, "127.0.0.1"}, @@ -445,7 +445,7 @@ TEST(NetUtilTest, NetAddressToString_IPv6) { const struct { uint8 addr[16]; - const char* result; + const char* const result; } tests[] = { {{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}, @@ -494,8 +494,8 @@ TEST(NetUtilTest, SimplifyUrlForRequest) { struct { - const char* input_url; - const char* expected_simplified_url; + const char* const input_url; + const char* const expected_simplified_url; } tests[] = { { // Reference section should be stripped. @@ -661,7 +661,7 @@ // Test parsing invalid CIDR notation literals. TEST(NetUtilTest, ParseCIDRBlock_Invalid) { - const char* bad_literals[] = { + const char* const bad_literals[] = { "foobar", "", "192.168.0.1", @@ -702,8 +702,8 @@ TEST(NetUtilTest, IPNumberMatchesPrefix) { struct { - const char* cidr_literal; - const char* ip_literal; + const char* const cidr_literal; + const char* const ip_literal; bool expected_to_match; } tests[] = { // IPv4 prefix with IPv4 inputs. @@ -1417,7 +1417,7 @@ struct NonUniqueNameTestData { bool is_unique; - const char* hostname; + const char* const hostname; }; // Google Test pretty-printer.
diff --git a/net/base/network_change_notifier.cc b/net/base/network_change_notifier.cc index 34ec592..2e573dc 100644 --- a/net/base/network_change_notifier.cc +++ b/net/base/network_change_notifier.cc
@@ -555,7 +555,7 @@ // static const char* NetworkChangeNotifier::ConnectionTypeToString( ConnectionType type) { - static const char* kConnectionTypeNames[] = { + static const char* const kConnectionTypeNames[] = { "CONNECTION_UNKNOWN", "CONNECTION_ETHERNET", "CONNECTION_WIFI",
diff --git a/net/base/registry_controlled_domains/registry_controlled_domain_unittest.cc b/net/base/registry_controlled_domains/registry_controlled_domain_unittest.cc index 22bd963..42af173 100644 --- a/net/base/registry_controlled_domains/registry_controlled_domain_unittest.cc +++ b/net/base/registry_controlled_domains/registry_controlled_domain_unittest.cc
@@ -372,13 +372,13 @@ // is about 100 bytes and a one byte offset can at most add 64 bytes to // previous offset. Thus the paths must go over two byte offsets. - const char* key0 = + const char key0[] = "a.b.6____________________________________________________" "________________________________________________6"; - const char* key1 = + const char key1[] = "a.b.7____________________________________________________" "________________________________________________7"; - const char* key2 = + const char key2[] = "a.b.a____________________________________________________" "________________________________________________8"; @@ -405,13 +405,13 @@ // probability at least one of the tested paths has go over a three byte // offset. - const char* key0 = + const char key0[] = "a.b.Z6___________________________________________________" "_________________________________________________Z6"; - const char* key1 = + const char key1[] = "a.b.Z7___________________________________________________" "_________________________________________________Z7"; - const char* key2 = + const char key2[] = "a.b.Za___________________________________________________" "_________________________________________________Z8"; @@ -431,14 +431,14 @@ // suffixes. The DAFSA will then form a trie with the implicit source node // as root. - const char* key0 = "a.b.ai"; - const char* key1 = "a.b.bj"; - const char* key2 = "a.b.aak"; - const char* key3 = "a.b.bbl"; - const char* key4 = "a.b.aaa"; - const char* key5 = "a.b.bbb"; - const char* key6 = "a.b.aaaam"; - const char* key7 = "a.b.bbbbn"; + const char key0[] = "a.b.ai"; + const char key1[] = "a.b.bj"; + const char key2[] = "a.b.aak"; + const char key3[] = "a.b.bbl"; + const char key4[] = "a.b.aaa"; + const char key5[] = "a.b.bbb"; + const char key6[] = "a.b.aaaam"; + const char key7[] = "a.b.bbbbn"; EXPECT_EQ(2U, GetRegistryLengthFromHost(key0, EXCLUDE_UNKNOWN_REGISTRIES)); EXPECT_EQ(0U, GetRegistryLengthFromHost(key1, EXCLUDE_UNKNOWN_REGISTRIES)); @@ -468,14 +468,14 @@ // prefixes. The DAFSA will then form a trie with the implicit sink node as // root. - const char* key0 = "a.b.ia"; - const char* key1 = "a.b.jb"; - const char* key2 = "a.b.kaa"; - const char* key3 = "a.b.lbb"; - const char* key4 = "a.b.aaa"; - const char* key5 = "a.b.bbb"; - const char* key6 = "a.b.maaaa"; - const char* key7 = "a.b.nbbbb"; + const char key0[] = "a.b.ia"; + const char key1[] = "a.b.jb"; + const char key2[] = "a.b.kaa"; + const char key3[] = "a.b.lbb"; + const char key4[] = "a.b.aaa"; + const char key5[] = "a.b.bbb"; + const char key6[] = "a.b.maaaa"; + const char key7[] = "a.b.nbbbb"; EXPECT_EQ(2U, GetRegistryLengthFromHost(key0, EXCLUDE_UNKNOWN_REGISTRIES)); EXPECT_EQ(0U, GetRegistryLengthFromHost(key1, EXCLUDE_UNKNOWN_REGISTRIES));
diff --git a/net/cert/nss_cert_database_chromeos.h b/net/cert/nss_cert_database_chromeos.h index 171ce28..930f9f23 100644 --- a/net/cert/nss_cert_database_chromeos.h +++ b/net/cert/nss_cert_database_chromeos.h
@@ -18,19 +18,17 @@ public: NSSCertDatabaseChromeOS(crypto::ScopedPK11Slot public_slot, crypto::ScopedPK11Slot private_slot); - virtual ~NSSCertDatabaseChromeOS(); + ~NSSCertDatabaseChromeOS() override; // |system_slot| is the system TPM slot, which is only enabled for certain // users. void SetSystemSlot(crypto::ScopedPK11Slot system_slot); // NSSCertDatabase implementation. - virtual void ListCertsSync(CertificateList* certs) override; - virtual void ListCerts(const NSSCertDatabase::ListCertsCallback& callback) - override; - virtual void ListModules(CryptoModuleList* modules, bool need_rw) const - override; - virtual crypto::ScopedPK11Slot GetSystemSlot() const override; + void ListCertsSync(CertificateList* certs) override; + void ListCerts(const NSSCertDatabase::ListCertsCallback& callback) override; + void ListModules(CryptoModuleList* modules, bool need_rw) const override; + crypto::ScopedPK11Slot GetSystemSlot() const override; // TODO(mattm): handle trust setting, deletion, etc correctly when certs exist // in multiple slots.
diff --git a/net/cert/nss_cert_database_chromeos_unittest.cc b/net/cert/nss_cert_database_chromeos_unittest.cc index caf5ea9..cf41185f 100644 --- a/net/cert/nss_cert_database_chromeos_unittest.cc +++ b/net/cert/nss_cert_database_chromeos_unittest.cc
@@ -48,7 +48,7 @@ NSSCertDatabaseChromeOSTest() : observer_added_(false), user_1_("user1"), user_2_("user2") {} - virtual void SetUp() override { + void SetUp() override { // Initialize nss_util slots. ASSERT_TRUE(user_1_.constructed_successfully()); ASSERT_TRUE(user_2_.constructed_successfully()); @@ -77,19 +77,19 @@ observer_added_ = true; } - virtual void TearDown() override { + void TearDown() override { if (observer_added_) CertDatabase::GetInstance()->RemoveObserver(this); } // CertDatabase::Observer: - virtual void OnCertAdded(const X509Certificate* cert) override { + void OnCertAdded(const X509Certificate* cert) override { added_.push_back(cert ? cert->os_cert_handle() : NULL); } - virtual void OnCertRemoved(const X509Certificate* cert) override {} + void OnCertRemoved(const X509Certificate* cert) override {} - virtual void OnCACertChanged(const X509Certificate* cert) override { + void OnCACertChanged(const X509Certificate* cert) override { added_ca_.push_back(cert ? cert->os_cert_handle() : NULL); }
diff --git a/net/cert/nss_profile_filter_chromeos_unittest.cc b/net/cert/nss_profile_filter_chromeos_unittest.cc index 1ebf399..d4051af 100644 --- a/net/cert/nss_profile_filter_chromeos_unittest.cc +++ b/net/cert/nss_profile_filter_chromeos_unittest.cc
@@ -58,7 +58,7 @@ public: NSSProfileFilterChromeOSTest() : user_1_("user1"), user_2_("user2") {} - virtual void SetUp() override { + void SetUp() override { ASSERT_TRUE(system_slot_user_.is_open()); ASSERT_TRUE(user_1_.constructed_successfully()); ASSERT_TRUE(user_2_.constructed_successfully());
diff --git a/net/cert/x509_cert_types_win.cc b/net/cert/x509_cert_types_win.cc index 8a456f3b..f5f426d 100644 --- a/net/cert/x509_cert_types_win.cc +++ b/net/cert/x509_cert_types_win.cc
@@ -21,7 +21,7 @@ // A list of OIDs to decode. Any OID not on this list will be ignored for // purposes of parsing. -const char* kOIDs[] = { +const char* const kOIDs[] = { szOID_COMMON_NAME, szOID_LOCALITY_NAME, szOID_STATE_OR_PROVINCE_NAME,
diff --git a/net/cookies/cookie_constants_unittest.cc b/net/cookies/cookie_constants_unittest.cc index f14f11e1..87fa1c1b 100644 --- a/net/cookies/cookie_constants_unittest.cc +++ b/net/cookies/cookie_constants_unittest.cc
@@ -31,7 +31,8 @@ EXPECT_LT(COOKIE_PRIORITY_MEDIUM, COOKIE_PRIORITY_HIGH); // Unrecognized tokens are interpreted as COOKIE_PRIORITY_DEFAULT. - const char* bad_tokens[] = {"", "lo", "lowerest", "high ", " high", "0"}; + const char* const bad_tokens[] = { + "", "lo", "lowerest", "high ", " high", "0"}; for (size_t i = 0; i < arraysize(bad_tokens); ++i) { EXPECT_EQ(COOKIE_PRIORITY_DEFAULT, StringToCookiePriority(bad_tokens[i])); }
diff --git a/net/cookies/cookie_monster_perftest.cc b/net/cookies/cookie_monster_perftest.cc index 6e799ad..40dc9463 100644 --- a/net/cookies/cookie_monster_perftest.cc +++ b/net/cookies/cookie_monster_perftest.cc
@@ -186,7 +186,7 @@ scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL)); GetCookiesCallback getCookiesCallback; SetCookieCallback setCookieCallback; - const char* domain_cookie_format_tree = "a=b; domain=%s"; + const char domain_cookie_format_tree[] = "a=b; domain=%s"; const std::string domain_base("top.com"); std::vector<std::string> domain_list; @@ -256,7 +256,7 @@ domain_list.push_back("b.a.b.a.top.com"); EXPECT_EQ(4u, domain_list.size()); - const char* domain_cookie_format_line = "a%03d=b; domain=%s"; + const char domain_cookie_format_line[] = "a%03d=b; domain=%s"; for (int i = 0; i < 8; i++) { for (std::vector<std::string>::const_iterator it = domain_list.begin(); it != domain_list.end(); it++) { @@ -331,7 +331,7 @@ SetCookieCallback setCookieCallback; const struct TestCase { - const char* name; + const char* const name; size_t num_cookies; size_t num_old_cookies; } test_cases[] = {
diff --git a/net/cookies/cookie_monster_unittest.cc b/net/cookies/cookie_monster_unittest.cc index 633bca59..d5067ae7 100644 --- a/net/cookies/cookie_monster_unittest.cc +++ b/net/cookies/cookie_monster_unittest.cc
@@ -61,12 +61,12 @@ virtual ~NewMockPersistentCookieStore() {} }; -const char* kTopLevelDomainPlus1 = "http://www.harvard.edu"; -const char* kTopLevelDomainPlus2 = "http://www.math.harvard.edu"; -const char* kTopLevelDomainPlus2Secure = "https://www.math.harvard.edu"; -const char* kTopLevelDomainPlus3 = +const char kTopLevelDomainPlus1[] = "http://www.harvard.edu"; +const char kTopLevelDomainPlus2[] = "http://www.math.harvard.edu"; +const char kTopLevelDomainPlus2Secure[] = "https://www.math.harvard.edu"; +const char kTopLevelDomainPlus3[] = "http://www.bourbaki.math.harvard.edu"; -const char* kOtherDomain = "http://www.mit.edu"; +const char kOtherDomain[] = "http://www.mit.edu"; const char kUrlGoogleSpecific[] = "http://www.gmail.google.izzle"; class GetCookieListCallback : public CookieCallback { @@ -1252,7 +1252,7 @@ scoped_refptr<CookieMonster> cm_foo(new CookieMonster(NULL, NULL)); // Only cm_foo should allow foo:// cookies. - const char* kSchemes[] = {"foo"}; + const char* const kSchemes[] = {"foo"}; cm_foo->SetCookieableSchemes(kSchemes, 1); GURL foo_url("foo://host/path");
diff --git a/net/cookies/cookie_util.cc b/net/cookies/cookie_util.cc index 9588018..075ad73c 100644 --- a/net/cookies/cookie_util.cc +++ b/net/cookies/cookie_util.cc
@@ -92,8 +92,9 @@ // An average cookie expiration will look something like this: // Sat, 15-Apr-17 21:01:22 GMT base::Time ParseCookieTime(const std::string& time_string) { - static const char* kMonths[] = { "jan", "feb", "mar", "apr", "may", "jun", - "jul", "aug", "sep", "oct", "nov", "dec" }; + static const char* const kMonths[] = { + "jan", "feb", "mar", "apr", "may", "jun", + "jul", "aug", "sep", "oct", "nov", "dec" }; static const int kMonthsLen = arraysize(kMonths); // We want to be pretty liberal, and support most non-ascii and non-digit // characters as a delimiter. We can't treat : as a delimiter, because it @@ -102,7 +103,7 @@ // If the cookie attribute came in in quotes (ex expires="XXX"), the quotes // will be preserved, and we will get them here. So we make sure to include // quote characters, and also \ for anything that was internally escaped. - static const char* kDelimiters = "\t !\"#$%&'()*+,-./;<=>?@[\\]^_`{|}~"; + static const char kDelimiters[] = "\t !\"#$%&'()*+,-./;<=>?@[\\]^_`{|}~"; base::Time::Exploded exploded = {0};
diff --git a/net/cookies/parsed_cookie_unittest.cc b/net/cookies/parsed_cookie_unittest.cc index 0f571551..30d41eb 100644 --- a/net/cookies/parsed_cookie_unittest.cc +++ b/net/cookies/parsed_cookie_unittest.cc
@@ -38,7 +38,7 @@ // handle differently. I've tested Internet Explorer 6, Opera 9.6, // Firefox 3, and Safari Windows 3.2.1. We originally tried to match // Firefox closely, however we now match Internet Explorer and Safari. - const char* values[] = { + const char* const values[] = { // Trailing whitespace after a quoted value. The whitespace after // the quote is stripped in all browsers. "\"zzz \" ", "\"zzz \"", @@ -471,14 +471,14 @@ TEST(ParsedCookieTest, ValidNonAlphanumericChars) { // Note that some of these words are pasted backwords thanks to poor vim bidi // support. This should not affect the tests, however. - const char* pc1_literal = "name=العربية"; - const char* pc2_literal = "name=普通話"; - const char* pc3_literal = "name=ภาษาไทย"; - const char* pc4_literal = "name=עִבְרִית"; - const char* pc5_literal = "العربية=value"; - const char* pc6_literal = "普通話=value"; - const char* pc7_literal = "ภาษาไทย=value"; - const char* pc8_literal = "עִבְרִית=value"; + const char pc1_literal[] = "name=العربية"; + const char pc2_literal[] = "name=普通話"; + const char pc3_literal[] = "name=ภาษาไทย"; + const char pc4_literal[] = "name=עִבְרִית"; + const char pc5_literal[] = "العربية=value"; + const char pc6_literal[] = "普通話=value"; + const char pc7_literal[] = "ภาษาไทย=value"; + const char pc8_literal[] = "עִבְרִית=value"; ParsedCookie pc1(pc1_literal); ParsedCookie pc2(pc2_literal); ParsedCookie pc3(pc3_literal);
diff --git a/net/disk_cache/backend_unittest.cc b/net/disk_cache/backend_unittest.cc index 3b1f669..9c06839 100644 --- a/net/disk_cache/backend_unittest.cc +++ b/net/disk_cache/backend_unittest.cc
@@ -349,8 +349,8 @@ void DiskCacheBackendTest::BackendKeying() { InitCache(); - const char* kName1 = "the first key"; - const char* kName2 = "the first Key"; + const char kName1[] = "the first key"; + const char kName2[] = "the first Key"; disk_cache::Entry *entry1, *entry2; ASSERT_EQ(net::OK, CreateEntry(kName1, &entry1)); @@ -3231,7 +3231,7 @@ SetSimpleCacheMode(); InitCache(); - const char* key = "the first key"; + const char key[] = "the first key"; disk_cache::Entry* entry = NULL; ASSERT_EQ(net::OK, CreateEntry(key, &entry)); @@ -3267,7 +3267,7 @@ SetSimpleCacheMode(); InitCache(); - const char* key = "the first key"; + const char key[] = "the first key"; disk_cache::Entry* entry = NULL; ASSERT_EQ(net::OK, CreateEntry(key, &entry));
diff --git a/net/disk_cache/blockfile/backend_impl.cc b/net/disk_cache/blockfile/backend_impl.cc index bf76842c..980249bf 100644 --- a/net/disk_cache/blockfile/backend_impl.cc +++ b/net/disk_cache/blockfile/backend_impl.cc
@@ -41,7 +41,7 @@ namespace { -const char* kIndexName = "index"; +const char kIndexName[] = "index"; // Seems like ~240 MB correspond to less than 50k entries for 99% of the people. // Note that the actual target is to keep the index table load factor under 55%
diff --git a/net/disk_cache/blockfile/backend_impl_v3.cc b/net/disk_cache/blockfile/backend_impl_v3.cc index 0b0e2326..6d73d07 100644 --- a/net/disk_cache/blockfile/backend_impl_v3.cc +++ b/net/disk_cache/blockfile/backend_impl_v3.cc
@@ -230,7 +230,8 @@ } std::string BackendImplV3::HistogramName(const char* name) const { - static const char* names[] = { "Http", "", "Media", "AppCache", "Shader" }; + static const char* const names[] = { + "Http", "", "Media", "AppCache", "Shader" }; DCHECK_NE(cache_type_, net::MEMORY_CACHE); return base::StringPrintf("DiskCache3.%s_%s", name, names[cache_type_]); }
diff --git a/net/disk_cache/blockfile/backend_worker_v3.cc b/net/disk_cache/blockfile/backend_worker_v3.cc index 1d89de6..b0f3250 100644 --- a/net/disk_cache/blockfile/backend_worker_v3.cc +++ b/net/disk_cache/blockfile/backend_worker_v3.cc
@@ -26,7 +26,7 @@ #if defined(V3_NOT_JUST_YET_READY) -const char* kIndexName = "index"; +const char kIndexName[] = "index"; // Seems like ~240 MB correspond to less than 50k entries for 99% of the people. // Note that the actual target is to keep the index table load factor under 55%
diff --git a/net/disk_cache/blockfile/block_files.cc b/net/disk_cache/blockfile/block_files.cc index 525141b..9aa8f0f1 100644 --- a/net/disk_cache/blockfile/block_files.cc +++ b/net/disk_cache/blockfile/block_files.cc
@@ -20,7 +20,7 @@ namespace { -const char* kBlockName = "data_"; +const char kBlockName[] = "data_"; // This array is used to perform a fast lookup of the nibble bit pattern to the // type of entry that can be stored there (number of consecutive blocks).
diff --git a/net/disk_cache/blockfile/stats.cc b/net/disk_cache/blockfile/stats.cc index fae006d..e6b10b8 100644 --- a/net/disk_cache/blockfile/stats.cc +++ b/net/disk_cache/blockfile/stats.cc
@@ -43,7 +43,7 @@ } // WARNING: Add new stats only at the end, or change LoadStats(). -static const char* kCounterNames[] = { +const char* const kCounterNames[] = { "Open miss", "Open hit", "Create miss",
diff --git a/net/dns/address_sorter_posix_unittest.cc b/net/dns/address_sorter_posix_unittest.cc index 5dcfe709..88a135fe 100644 --- a/net/dns/address_sorter_posix_unittest.cc +++ b/net/dns/address_sorter_posix_unittest.cc
@@ -151,9 +151,9 @@ // Verify that NULL-terminated |addresses| matches (-1)-terminated |order| // after sorting. - void Verify(const char* addresses[], const int order[]) { + void Verify(const char* const addresses[], const int order[]) { AddressList list; - for (const char** addr = addresses; *addr != NULL; ++addr) + for (const char* const* addr = addresses; *addr != NULL; ++addr) list.push_back(IPEndPoint(ParseIP(*addr), 80)); for (size_t i = 0; order[i] >= 0; ++i) CHECK_LT(order[i], static_cast<int>(list.size())); @@ -181,7 +181,7 @@ // Rule 1: Avoid unusable destinations. TEST_F(AddressSorterPosixTest, Rule1) { AddMapping("10.0.0.231", "10.0.0.1"); - const char* addresses[] = { "::1", "10.0.0.231", "127.0.0.1", NULL }; + const char* const addresses[] = { "::1", "10.0.0.231", "127.0.0.1", NULL }; const int order[] = { 1, -1 }; Verify(addresses, order); } @@ -196,11 +196,11 @@ AddMapping("8.0.0.1", "169.254.0.10"); // global vs. link-local // In all three cases, matching scope is preferred. const int order[] = { 1, 0, -1 }; - const char* addresses1[] = { "3002::2", "3002::1", NULL }; + const char* const addresses1[] = { "3002::2", "3002::1", NULL }; Verify(addresses1, order); - const char* addresses2[] = { "fec1::2", "ff32::1", NULL }; + const char* const addresses2[] = { "fec1::2", "ff32::1", NULL }; Verify(addresses2, order); - const char* addresses3[] = { "8.0.0.1", "fec1::1", NULL }; + const char* const addresses3[] = { "8.0.0.1", "fec1::1", NULL }; Verify(addresses3, order); } @@ -210,7 +210,7 @@ AddMapping("3002::1", "4000::10"); GetSourceInfo("4000::10")->deprecated = true; AddMapping("3002::2", "4000::20"); - const char* addresses[] = { "3002::1", "3002::2", NULL }; + const char* const addresses[] = { "3002::1", "3002::2", NULL }; const int order[] = { 1, 0, -1 }; Verify(addresses, order); } @@ -220,7 +220,7 @@ AddMapping("3002::1", "4000::10"); AddMapping("3002::2", "4000::20"); GetSourceInfo("4000::20")->home = true; - const char* addresses[] = { "3002::1", "3002::2", NULL }; + const char* const addresses[] = { "3002::1", "3002::2", NULL }; const int order[] = { 1, 0, -1 }; Verify(addresses, order); } @@ -233,11 +233,11 @@ AddMapping("2002::1", "2001::10"); // 6to4 vs. Teredo const int order[] = { 1, 0, -1 }; { - const char* addresses[] = { "2001::1", "::1", NULL }; + const char* const addresses[] = { "2001::1", "::1", NULL }; Verify(addresses, order); } { - const char* addresses[] = { "2002::1", "::ffff:1234:1", NULL }; + const char* const addresses[] = { "2002::1", "::ffff:1234:1", NULL }; Verify(addresses, order); } } @@ -248,8 +248,8 @@ AddMapping("ff32::1", "fe81::10"); // multicast AddMapping("::ffff:1234:1", "::ffff:1234:10"); // IPv4-mapped AddMapping("2001::1", "2001::10"); // Teredo - const char* addresses[] = { "2001::1", "::ffff:1234:1", "ff32::1", "::1", - NULL }; + const char* const addresses[] = { "2001::1", "::ffff:1234:1", "ff32::1", + "::1", NULL }; const int order[] = { 3, 2, 1, 0, -1 }; Verify(addresses, order); } @@ -259,7 +259,7 @@ AddMapping("3002::1", "4000::10"); AddMapping("3002::2", "4000::20"); GetSourceInfo("4000::20")->native = true; - const char* addresses[] = { "3002::1", "3002::2", NULL }; + const char* const addresses[] = { "3002::1", "3002::2", NULL }; const int order[] = { 1, 0, -1 }; Verify(addresses, order); } @@ -273,8 +273,8 @@ AddMapping("ff32::1", "4000::10"); // link-local AddMapping("ff35::1", "4000::10"); // site-local AddMapping("ff38::1", "4000::10"); // org-local - const char* addresses[] = { "ff38::1", "3000::1", "ff35::1", "ff32::1", - "fe81::1", NULL }; + const char* const addresses[] = { "ff38::1", "3000::1", "ff35::1", "ff32::1", + "fe81::1", NULL }; const int order[] = { 4, 1, 3, 2, 0, -1 }; Verify(addresses, order); } @@ -287,8 +287,8 @@ GetSourceInfo("4000::10")->prefix_length = 15; AddMapping("4002::1", "4000::10"); // 14 bit match AddMapping("4080::1", "4000::10"); // 8 bit match - const char* addresses[] = { "4080::1", "4002::1", "4000::1", "3000::1", - NULL }; + const char* const addresses[] = { "4080::1", "4002::1", "4000::1", "3000::1", + NULL }; const int order[] = { 3, 2, 1, 0, -1 }; Verify(addresses, order); } @@ -298,7 +298,7 @@ AddMapping("4000::1", "4000::10"); AddMapping("4000::2", "4000::10"); AddMapping("4000::3", "4000::10"); - const char* addresses[] = { "4000::1", "4000::2", "4000::3", NULL }; + const char* const addresses[] = { "4000::1", "4000::2", "4000::3", NULL }; const int order[] = { 0, 1, 2, -1 }; Verify(addresses, order); } @@ -310,8 +310,8 @@ AddMapping("4000::1", "4000::10"); // global unicast AddMapping("ff32::2", "fe81::20"); // deprecated link-local multicast GetSourceInfo("fe81::20")->deprecated = true; - const char* addresses[] = { "ff3e::1", "ff32::2", "4000::1", "ff32::1", "::1", - "8.0.0.1", NULL }; + const char* const addresses[] = { "ff3e::1", "ff32::2", "4000::1", "ff32::1", + "::1", "8.0.0.1", NULL }; const int order[] = { 4, 3, 0, 2, 1, -1 }; Verify(addresses, order); }
diff --git a/net/dns/dns_config_service_posix_unittest.cc b/net/dns/dns_config_service_posix_unittest.cc index 1bfbe089..b208ffd7 100644 --- a/net/dns/dns_config_service_posix_unittest.cc +++ b/net/dns/dns_config_service_posix_unittest.cc
@@ -15,7 +15,7 @@ namespace { // MAXNS is normally 3, but let's test 4 if possible. -const char* kNameserversIPv4[] = { +const char* const kNameserversIPv4[] = { "8.8.8.8", "192.168.1.1", "63.1.2.4", @@ -23,7 +23,7 @@ }; #if defined(OS_LINUX) -const char* kNameserversIPv6[] = { +const char* const kNameserversIPv6[] = { NULL, "2001:DB8:0::42", NULL,
diff --git a/net/ftp/ftp_directory_listing_parser.cc b/net/ftp/ftp_directory_listing_parser.cc index fa6e8a5386..31cb462 100644 --- a/net/ftp/ftp_directory_listing_parser.cc +++ b/net/ftp/ftp_directory_listing_parser.cc
@@ -95,7 +95,7 @@ const base::Time& current_time, std::vector<FtpDirectoryListingEntry>* entries, FtpServerType* server_type) { - const char* kNewlineSeparators[] = { "\n", "\r\n" }; + const char* const kNewlineSeparators[] = { "\n", "\r\n" }; std::vector<std::string> encodings; if (!base::DetectAllEncodings(text, &encodings))
diff --git a/net/ftp/ftp_directory_listing_parser_ls_unittest.cc b/net/ftp/ftp_directory_listing_parser_ls_unittest.cc index 313ef664..6657de9b 100644 --- a/net/ftp/ftp_directory_listing_parser_ls_unittest.cc +++ b/net/ftp/ftp_directory_listing_parser_ls_unittest.cc
@@ -167,7 +167,7 @@ } TEST_F(FtpDirectoryListingParserLsTest, Ignored) { - const char* ignored_cases[] = { + const char* const ignored_cases[] = { "drwxr-xr-x 2 0 0 4096 Mar 18 2007 ", // http://crbug.com/60065 "ftpd: .: Permission denied", @@ -194,7 +194,7 @@ } TEST_F(FtpDirectoryListingParserLsTest, Bad) { - const char* bad_cases[] = { + const char* const bad_cases[] = { " foo", "garbage", "-rw-r--r-- ftp ftp",
diff --git a/net/ftp/ftp_directory_listing_parser_netware_unittest.cc b/net/ftp/ftp_directory_listing_parser_netware_unittest.cc index 102552c..11c695f8 100644 --- a/net/ftp/ftp_directory_listing_parser_netware_unittest.cc +++ b/net/ftp/ftp_directory_listing_parser_netware_unittest.cc
@@ -47,7 +47,7 @@ } TEST_F(FtpDirectoryListingParserNetwareTest, Bad) { - const char* bad_cases[] = { + const char* const bad_cases[] = { " foo", "garbage", "d [] ftpadmin 512 Jan 29 2004 pub",
diff --git a/net/ftp/ftp_directory_listing_parser_os2_unittest.cc b/net/ftp/ftp_directory_listing_parser_os2_unittest.cc index 7302f4c9..3288a22 100644 --- a/net/ftp/ftp_directory_listing_parser_os2_unittest.cc +++ b/net/ftp/ftp_directory_listing_parser_os2_unittest.cc
@@ -64,7 +64,7 @@ } TEST_F(FtpDirectoryListingParserOS2Test, Ignored) { - const char* ignored_cases[] = { + const char* const ignored_cases[] = { "1234 A 12-07-10 12:05", "0 DIR 11-02-09 05:32", }; @@ -81,7 +81,7 @@ } TEST_F(FtpDirectoryListingParserOS2Test, Bad) { - const char* bad_cases[] = { + const char* const bad_cases[] = { "garbage", "0 GARBAGE 11-02-09 05:32", "0 GARBAGE 11-02-09 05:32 NT",
diff --git a/net/ftp/ftp_directory_listing_parser_unittest.cc b/net/ftp/ftp_directory_listing_parser_unittest.cc index 70795e5..79af5c3 100644 --- a/net/ftp/ftp_directory_listing_parser_unittest.cc +++ b/net/ftp/ftp_directory_listing_parser_unittest.cc
@@ -104,7 +104,7 @@ } } -const char* kTestFiles[] = { +const char* const kTestFiles[] = { "dir-listing-ls-1", "dir-listing-ls-1-utf8", "dir-listing-ls-2",
diff --git a/net/ftp/ftp_directory_listing_parser_vms.cc b/net/ftp/ftp_directory_listing_parser_vms.cc index c568c0a..05e687f 100644 --- a/net/ftp/ftp_directory_listing_parser_vms.cc +++ b/net/ftp/ftp_directory_listing_parser_vms.cc
@@ -133,7 +133,7 @@ } bool LooksLikeVMSError(const base::string16& text) { - static const char* kPermissionDeniedMessages[] = { + static const char* const kPermissionDeniedMessages[] = { "%RMS-E-FNF", // File not found. "%RMS-E-PRV", // Access denied. "%SYSTEM-F-NOPRIV",
diff --git a/net/ftp/ftp_directory_listing_parser_vms_unittest.cc b/net/ftp/ftp_directory_listing_parser_vms_unittest.cc index cef86c0..08ee9e1 100644 --- a/net/ftp/ftp_directory_listing_parser_vms_unittest.cc +++ b/net/ftp/ftp_directory_listing_parser_vms_unittest.cc
@@ -75,7 +75,7 @@ } TEST_F(FtpDirectoryListingParserVmsTest, Bad) { - const char* bad_cases[] = { + const char* const bad_cases[] = { "garbage", // Missing file version number. @@ -128,7 +128,7 @@ } TEST_F(FtpDirectoryListingParserVmsTest, BadDataAfterFooter) { - const char* bad_cases[] = { + const char* const bad_cases[] = { "garbage", "Total of 1 file, 2 blocks.", "Directory ANYNYMOUS_ROOT:[000000]",
diff --git a/net/ftp/ftp_directory_listing_parser_windows_unittest.cc b/net/ftp/ftp_directory_listing_parser_windows_unittest.cc index d3d47da..1c6234e 100644 --- a/net/ftp/ftp_directory_listing_parser_windows_unittest.cc +++ b/net/ftp/ftp_directory_listing_parser_windows_unittest.cc
@@ -70,7 +70,7 @@ } TEST_F(FtpDirectoryListingParserWindowsTest, Ignored) { - const char* ignored_cases[] = { + const char* const ignored_cases[] = { "12-07-10 12:05AM <DIR> ", // http://crbug.com/66097 "12-07-10 12:05AM 1234 ", "11-02-09 05:32 <DIR>", @@ -89,7 +89,7 @@ } TEST_F(FtpDirectoryListingParserWindowsTest, Bad) { - const char* bad_cases[] = { + const char* const bad_cases[] = { "garbage", "11-02-09 05:32PM <GARBAGE>", "11-02-09 05:32PM <GARBAGE> NT",
diff --git a/net/ftp/ftp_network_transaction_unittest.cc b/net/ftp/ftp_network_transaction_unittest.cc index 4ee812d..ad748c9d 100644 --- a/net/ftp/ftp_network_transaction_unittest.cc +++ b/net/ftp/ftp_network_transaction_unittest.cc
@@ -72,8 +72,9 @@ "331 Password needed\r\n"); case PRE_PASSWD: { - const char* response_one = "230 Welcome\r\n"; - const char* response_multi = "230- One\r\n230- Two\r\n230 Three\r\n"; + static const char response_one[] = "230 Welcome\r\n"; + static const char response_multi[] = + "230- One\r\n230- Two\r\n230 Three\r\n"; return Verify("PASS chrome@example.com\r\n", data, PRE_SYST, multiline_welcome_ ? response_multi : response_one); }
diff --git a/net/http/http_auth_cache_unittest.cc b/net/http/http_auth_cache_unittest.cc index 3565b0c..18866eaa 100644 --- a/net/http/http_auth_cache_unittest.cc +++ b/net/http/http_auth_cache_unittest.cc
@@ -55,11 +55,11 @@ ~MockAuthHandler() override {} }; -const char* kRealm1 = "Realm1"; -const char* kRealm2 = "Realm2"; -const char* kRealm3 = "Realm3"; -const char* kRealm4 = "Realm4"; -const char* kRealm5 = "Realm5"; +const char kRealm1[] = "Realm1"; +const char kRealm2[] = "Realm2"; +const char kRealm3[] = "Realm3"; +const char kRealm4[] = "Realm4"; +const char kRealm5[] = "Realm5"; const base::string16 k123(ASCIIToUTF16("123")); const base::string16 k1234(ASCIIToUTF16("1234")); const base::string16 kAdmin(ASCIIToUTF16("admin"));
diff --git a/net/http/http_cache_unittest.cc b/net/http/http_cache_unittest.cc index 16a5523..cee0c4a5 100644 --- a/net/http/http_cache_unittest.cc +++ b/net/http/http_cache_unittest.cc
@@ -2323,7 +2323,7 @@ MockHttpCache cache; // The URL we will be requesting. - const char* kUrl = "http://foobar.com/main.css"; + const char kUrl[] = "http://foobar.com/main.css"; // Junk network response. static const Response kUnexpectedResponse = { @@ -2434,7 +2434,7 @@ "body2" }; - const char* extra_headers = + const char extra_headers[] = "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\r\n"; ConditionalizedRequestUpdatesCacheHelper( @@ -2462,7 +2462,7 @@ "body2" }; - const char* extra_headers = "If-None-Match: \"ETAG1\"\r\n"; + const char extra_headers[] = "If-None-Match: \"ETAG1\"\r\n"; ConditionalizedRequestUpdatesCacheHelper( kNetResponse1, kNetResponse2, kNetResponse2, extra_headers); @@ -2498,7 +2498,7 @@ "body1" }; - const char* extra_headers = + const char extra_headers[] = "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\r\n"; ConditionalizedRequestUpdatesCacheHelper( @@ -2511,7 +2511,7 @@ TEST(HttpCache, ConditionalizedRequestUpdatesCache4) { MockHttpCache cache; - const char* kUrl = "http://foobar.com/main.css"; + const char kUrl[] = "http://foobar.com/main.css"; static const Response kNetResponse = { "HTTP/1.1 304 Not Modified", @@ -2520,7 +2520,7 @@ "" }; - const char* kExtraRequestHeaders = + const char kExtraRequestHeaders[] = "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\r\n"; // We will control the network layer's responses for |kUrl| using @@ -2555,7 +2555,7 @@ TEST(HttpCache, ConditionalizedRequestUpdatesCache5) { MockHttpCache cache; - const char* kUrl = "http://foobar.com/main.css"; + const char kUrl[] = "http://foobar.com/main.css"; static const Response kNetResponse = { "HTTP/1.1 200 OK", @@ -2564,7 +2564,7 @@ "foobar!!!" }; - const char* kExtraRequestHeaders = + const char kExtraRequestHeaders[] = "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\r\n"; // We will control the network layer's responses for |kUrl| using @@ -2617,7 +2617,7 @@ // This is two days in the future from the original response's last-modified // date! - const char* kExtraRequestHeaders = + const char kExtraRequestHeaders[] = "If-Modified-Since: Fri, 08 Feb 2008 22:38:21 GMT\r\n"; ConditionalizedRequestUpdatesCacheHelper( @@ -2646,7 +2646,7 @@ }; // Different etag from original response. - const char* kExtraRequestHeaders = "If-None-Match: \"Foo2\"\r\n"; + const char kExtraRequestHeaders[] = "If-None-Match: \"Foo2\"\r\n"; ConditionalizedRequestUpdatesCacheHelper( kNetResponse1, kNetResponse2, kNetResponse1, kExtraRequestHeaders); @@ -2672,7 +2672,7 @@ "body2" }; - const char* kExtraRequestHeaders = + const char kExtraRequestHeaders[] = "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\r\n" "If-None-Match: \"Foo1\"\r\n"; @@ -2701,7 +2701,7 @@ }; // The etag doesn't match what we have stored. - const char* kExtraRequestHeaders = + const char kExtraRequestHeaders[] = "If-Modified-Since: Wed, 06 Feb 2008 22:38:21 GMT\r\n" "If-None-Match: \"Foo2\"\r\n"; @@ -2730,7 +2730,7 @@ }; // The modification date doesn't match what we have stored. - const char* kExtraRequestHeaders = + const char kExtraRequestHeaders[] = "If-Modified-Since: Fri, 08 Feb 2008 22:38:21 GMT\r\n" "If-None-Match: \"Foo1\"\r\n"; @@ -6366,8 +6366,8 @@ TEST(HttpCache, UpdatesRequestResponseTimeOn304) { MockHttpCache cache; - const char* kUrl = "http://foobar"; - const char* kData = "body"; + const char kUrl[] = "http://foobar"; + const char kData[] = "body"; MockTransaction mock_network_response = { 0 }; mock_network_response.url = kUrl;
diff --git a/net/http/http_chunked_decoder_unittest.cc b/net/http/http_chunked_decoder_unittest.cc index f3e8300..db32c6f 100644 --- a/net/http/http_chunked_decoder_unittest.cc +++ b/net/http/http_chunked_decoder_unittest.cc
@@ -15,7 +15,8 @@ typedef testing::Test HttpChunkedDecoderTest; -void RunTest(const char* inputs[], size_t num_inputs, +void RunTest(const char* const inputs[], + size_t num_inputs, const char* expected_output, bool expected_eof, int bytes_after_eof) { @@ -38,7 +39,7 @@ } // Feed the inputs to the decoder, until it returns an error. -void RunTestUntilFailure(const char* inputs[], +void RunTestUntilFailure(const char* const inputs[], size_t num_inputs, size_t fail_index) { HttpChunkedDecoder decoder; @@ -57,21 +58,21 @@ } TEST(HttpChunkedDecoderTest, Basic) { - const char* inputs[] = { + const char* const inputs[] = { "B\r\nhello hello\r\n0\r\n\r\n" }; RunTest(inputs, arraysize(inputs), "hello hello", true, 0); } TEST(HttpChunkedDecoderTest, OneChunk) { - const char* inputs[] = { + const char* const inputs[] = { "5\r\nhello\r\n" }; RunTest(inputs, arraysize(inputs), "hello", false, 0); } TEST(HttpChunkedDecoderTest, Typical) { - const char* inputs[] = { + const char* const inputs[] = { "5\r\nhello\r\n", "1\r\n \r\n", "5\r\nworld\r\n", @@ -81,7 +82,7 @@ } TEST(HttpChunkedDecoderTest, Incremental) { - const char* inputs[] = { + const char* const inputs[] = { "5", "\r", "\n", @@ -99,7 +100,7 @@ // Same as above, but group carriage returns with previous input. TEST(HttpChunkedDecoderTest, Incremental2) { - const char* inputs[] = { + const char* const inputs[] = { "5\r", "\n", "hello\r", @@ -115,7 +116,7 @@ // Compatibility: [RFC 2616 - Invalid] // {Firefox3} - Valid // {IE7, Safari3.1, Opera9.51} - Invalid - const char* inputs[] = { + const char* const inputs[] = { "5\nhello\n", "1\n \n", "5\nworld\n", @@ -125,7 +126,7 @@ } TEST(HttpChunkedDecoderTest, Extensions) { - const char* inputs[] = { + const char* const inputs[] = { "5;x=0\r\nhello\r\n", "0;y=\"2 \"\r\n\r\n" }; @@ -133,7 +134,7 @@ } TEST(HttpChunkedDecoderTest, Trailers) { - const char* inputs[] = { + const char* const inputs[] = { "5\r\nhello\r\n", "0\r\n", "Foo: 1\r\n", @@ -144,7 +145,7 @@ } TEST(HttpChunkedDecoderTest, TrailersUnfinished) { - const char* inputs[] = { + const char* const inputs[] = { "5\r\nhello\r\n", "0\r\n", "Foo: 1\r\n" @@ -153,7 +154,7 @@ } TEST(HttpChunkedDecoderTest, InvalidChunkSize_TooBig) { - const char* inputs[] = { + const char* const inputs[] = { // This chunked body is not terminated. // However we will fail decoding because the chunk-size // number is larger than we can handle. @@ -164,7 +165,7 @@ } TEST(HttpChunkedDecoderTest, InvalidChunkSize_0X) { - const char* inputs[] = { + const char* const inputs[] = { // Compatibility [RFC 2616 - Invalid]: // {Safari3.1, IE7} - Invalid // {Firefox3, Opera 9.51} - Valid @@ -175,7 +176,7 @@ } TEST(HttpChunkedDecoderTest, ChunkSize_TrailingSpace) { - const char* inputs[] = { + const char* const inputs[] = { // Compatibility [RFC 2616 - Invalid]: // {IE7, Safari3.1, Firefox3, Opera 9.51} - Valid // @@ -187,7 +188,7 @@ } TEST(HttpChunkedDecoderTest, InvalidChunkSize_TrailingTab) { - const char* inputs[] = { + const char* const inputs[] = { // Compatibility [RFC 2616 - Invalid]: // {IE7, Safari3.1, Firefox3, Opera 9.51} - Valid "5\t\r\nhello\r\n", @@ -197,7 +198,7 @@ } TEST(HttpChunkedDecoderTest, InvalidChunkSize_TrailingFormFeed) { - const char* inputs[] = { + const char* const inputs[] = { // Compatibility [RFC 2616- Invalid]: // {Safari3.1} - Invalid // {IE7, Firefox3, Opera 9.51} - Valid @@ -208,7 +209,7 @@ } TEST(HttpChunkedDecoderTest, InvalidChunkSize_TrailingVerticalTab) { - const char* inputs[] = { + const char* const inputs[] = { // Compatibility [RFC 2616 - Invalid]: // {Safari 3.1} - Invalid // {IE7, Firefox3, Opera 9.51} - Valid @@ -219,7 +220,7 @@ } TEST(HttpChunkedDecoderTest, InvalidChunkSize_TrailingNonHexDigit) { - const char* inputs[] = { + const char* const inputs[] = { // Compatibility [RFC 2616 - Invalid]: // {Safari 3.1} - Invalid // {IE7, Firefox3, Opera 9.51} - Valid @@ -230,7 +231,7 @@ } TEST(HttpChunkedDecoderTest, InvalidChunkSize_LeadingSpace) { - const char* inputs[] = { + const char* const inputs[] = { // Compatibility [RFC 2616 - Invalid]: // {IE7} - Invalid // {Safari 3.1, Firefox3, Opera 9.51} - Valid @@ -241,7 +242,7 @@ } TEST(HttpChunkedDecoderTest, InvalidLeadingSeparator) { - const char* inputs[] = { + const char* const inputs[] = { "\r\n5\r\nhello\r\n", "0\r\n\r\n" }; @@ -249,7 +250,7 @@ } TEST(HttpChunkedDecoderTest, InvalidChunkSize_NoSeparator) { - const char* inputs[] = { + const char* const inputs[] = { "5\r\nhello", "1\r\n \r\n", "0\r\n\r\n" @@ -258,7 +259,7 @@ } TEST(HttpChunkedDecoderTest, InvalidChunkSize_Negative) { - const char* inputs[] = { + const char* const inputs[] = { "8\r\n12345678\r\n-5\r\nhello\r\n", "0\r\n\r\n" }; @@ -266,7 +267,7 @@ } TEST(HttpChunkedDecoderTest, InvalidChunkSize_Plus) { - const char* inputs[] = { + const char* const inputs[] = { // Compatibility [RFC 2616 - Invalid]: // {IE7, Safari 3.1} - Invalid // {Firefox3, Opera 9.51} - Valid @@ -277,7 +278,7 @@ } TEST(HttpChunkedDecoderTest, InvalidConsecutiveCRLFs) { - const char* inputs[] = { + const char* const inputs[] = { "5\r\nhello\r\n", "\r\n\r\n\r\n\r\n", "0\r\n\r\n" @@ -286,21 +287,21 @@ } TEST(HttpChunkedDecoderTest, ExcessiveChunkLen) { - const char* inputs[] = { + const char* const inputs[] = { "c0000000\r\nhello\r\n" }; RunTestUntilFailure(inputs, arraysize(inputs), 0); } TEST(HttpChunkedDecoderTest, BasicExtraData) { - const char* inputs[] = { + const char* const inputs[] = { "5\r\nhello\r\n0\r\n\r\nextra bytes" }; RunTest(inputs, arraysize(inputs), "hello", true, 11); } TEST(HttpChunkedDecoderTest, IncrementalExtraData) { - const char* inputs[] = { + const char* const inputs[] = { "5", "\r", "\n", @@ -317,7 +318,7 @@ } TEST(HttpChunkedDecoderTest, MultipleExtraDataBlocks) { - const char* inputs[] = { + const char* const inputs[] = { "5\r\nhello\r\n0\r\n\r\nextra", " bytes" }; @@ -330,7 +331,7 @@ scoped_ptr<char[]> big_chunk(new char[big_chunk_length + 1]); memset(big_chunk.get(), '0', big_chunk_length); big_chunk[big_chunk_length] = 0; - const char* inputs[] = { + const char* const inputs[] = { big_chunk.get(), "5" }; @@ -344,7 +345,7 @@ scoped_ptr<char[]> big_chunk(new char[big_chunk_length + 1]); memset(big_chunk.get(), '0', big_chunk_length); big_chunk[big_chunk_length] = 0; - const char* inputs[] = { + const char* const inputs[] = { "5;", big_chunk.get() };
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc index 50420db..3376051 100644 --- a/net/http/http_network_session.cc +++ b/net/http/http_network_session.cc
@@ -89,7 +89,6 @@ quic_always_require_handshake_confirmation(false), quic_disable_connection_pooling(false), quic_load_server_info_timeout_ms(0), - quic_disable_loading_server_info_for_new_servers(false), quic_load_server_info_timeout_srtt_multiplier(0.0f), quic_enable_truncated_connection_ids(false), quic_clock(NULL), @@ -135,7 +134,6 @@ params.quic_always_require_handshake_confirmation, params.quic_disable_connection_pooling, params.quic_load_server_info_timeout_ms, - params.quic_disable_loading_server_info_for_new_servers, params.quic_load_server_info_timeout_srtt_multiplier, params.quic_enable_truncated_connection_ids, params.quic_connection_options),
diff --git a/net/http/http_network_session.h b/net/http/http_network_session.h index d22a197..68b10db4 100644 --- a/net/http/http_network_session.h +++ b/net/http/http_network_session.h
@@ -117,7 +117,6 @@ bool quic_always_require_handshake_confirmation; bool quic_disable_connection_pooling; int quic_load_server_info_timeout_ms; - bool quic_disable_loading_server_info_for_new_servers; float quic_load_server_info_timeout_srtt_multiplier; bool quic_enable_truncated_connection_ids; HostPortPair origin_to_force_quic_on;
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc index a85e6ea..3812c60 100644 --- a/net/http/http_network_transaction_unittest.cc +++ b/net/http/http_network_transaction_unittest.cc
@@ -477,7 +477,7 @@ // Fill |str| with a long header list that consumes >= |size| bytes. void FillLargeHeadersString(std::string* str, int size) { - const char* row = + const char row[] = "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n"; const int sizeof_row = strlen(row); const int num_rows = static_cast<int>( @@ -1313,7 +1313,7 @@ StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0); session_deps_.socket_factory->AddSocketDataProvider(&data2); - const char* kExpectedResponseData[] = { + const char* const kExpectedResponseData[] = { "hello", "world" }; @@ -3425,7 +3425,7 @@ scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect( NULL, 0, 1, LOWEST, HostPortPair("www.google.com", 443))); // fetch https://www.google.com/ via SPDY - const char* const kMyUrl = "https://www.google.com/"; + const char kMyUrl[] = "https://www.google.com/"; scoped_ptr<SpdyFrame> get( spdy_util_.ConstructSpdyGet(kMyUrl, false, 1, LOWEST)); scoped_ptr<SpdyFrame> wrapped_get( @@ -5150,7 +5150,7 @@ session_deps_.socket_factory->AddSocketDataProvider(&data1); session_deps_.socket_factory->AddSocketDataProvider(&data2); - const char* kExpectedResponseData[] = { + const char* const kExpectedResponseData[] = { "hello world", "welcome" }; @@ -6498,7 +6498,7 @@ // The proxy responds to the connect with a 407, using a persistent // connection. - const char* const kAuthStatus = "407"; + const char kAuthStatus[] = "407"; const char* const kAuthChallenge[] = { "proxy-authenticate", "Basic realm=\"MyRealm1\"", }; @@ -9549,10 +9549,10 @@ static const int kNoSSL = 500; struct TestConfig { - const char* proxy_url; + const char* const proxy_url; AuthTiming proxy_auth_timing; int proxy_auth_rv; - const char* server_url; + const char* const server_url; AuthTiming server_auth_timing; int server_auth_rv; int num_auth_rounds; @@ -9934,7 +9934,7 @@ writes, arraysize(writes)); session_deps_.socket_factory->AddSocketDataProvider(&data_provider); - const char* const kSocketGroup = "www.example.com:80"; + const char kSocketGroup[] = "www.example.com:80"; // First round of authentication. auth_handler->SetGenerateExpectation(false, OK);
diff --git a/net/http/http_response_headers.cc b/net/http/http_response_headers.cc index c3fd958..3aef42a6 100644 --- a/net/http/http_response_headers.cc +++ b/net/http/http_response_headers.cc
@@ -1214,9 +1214,10 @@ // NOTE: It is perhaps risky to assume that a Proxy-Connection header is // meaningful when we don't know that this response was from a proxy, but // Mozilla also does this, so we'll do the same. - static const char* kConnectionHeaders[] = {"connection", "proxy-connection"}; + static const char* const kConnectionHeaders[] = { + "connection", "proxy-connection"}; struct KeepAliveToken { - const char* token; + const char* const token; bool keep_alive; }; static const KeepAliveToken kKeepAliveTokens[] = {{"keep-alive", true},
diff --git a/net/http/http_server_properties_impl.cc b/net/http/http_server_properties_impl.cc index a8bc04a6..d048e988 100644 --- a/net/http/http_server_properties_impl.cc +++ b/net/http/http_server_properties_impl.cc
@@ -227,17 +227,10 @@ const HostPortPair& server) { if (g_forced_alternate_protocol) return true; - AlternateProtocolMap::const_iterator it = alternate_protocol_map_.Get(server); - if (it != alternate_protocol_map_.end()) - return it->second.probability >= alternate_protocol_probability_threshold_; - - auto canonical = GetCanonicalHost(server); - if (canonical == canonical_host_to_origin_map_.end() || - canonical->second.Equals(server)) { - return false; - } - - return HasAlternateProtocol(canonical->second); + AlternateProtocolMap::const_iterator it = + GetAlternateProtocolIterator(server); + return it != alternate_protocol_map_.end() && + it->second.probability >= alternate_protocol_probability_threshold_; } std::string HttpServerPropertiesImpl::GetCanonicalSuffix( @@ -258,16 +251,11 @@ const HostPortPair& server) { DCHECK(HasAlternateProtocol(server)); - // First check the map. - AlternateProtocolMap::iterator it = alternate_protocol_map_.Get(server); + AlternateProtocolMap::const_iterator it = + GetAlternateProtocolIterator(server); if (it != alternate_protocol_map_.end()) return it->second; - // Next check the canonical host. - CanonicalHostMap::const_iterator canonical_host = GetCanonicalHost(server); - if (canonical_host != canonical_host_to_origin_map_.end()) - return alternate_protocol_map_.Get(canonical_host->second)->second; - // We must be forcing an alternate. DCHECK(g_forced_alternate_protocol); return *g_forced_alternate_protocol; @@ -282,9 +270,10 @@ AlternateProtocolInfo alternate(alternate_port, alternate_protocol, alternate_probability); - if (HasAlternateProtocol(server)) { - const AlternateProtocolInfo existing_alternate = - GetAlternateProtocol(server); + AlternateProtocolMap::const_iterator it = + GetAlternateProtocolIterator(server); + if (it != alternate_protocol_map_.end()) { + const AlternateProtocolInfo existing_alternate = it->second; if (existing_alternate.is_broken) { DVLOG(1) << "Ignore alternate protocol since it's known to be broken."; @@ -478,6 +467,20 @@ alternate_protocol_probability_threshold_ = threshold; } +AlternateProtocolMap::const_iterator +HttpServerPropertiesImpl::GetAlternateProtocolIterator( + const HostPortPair& server) { + AlternateProtocolMap::const_iterator it = alternate_protocol_map_.Get(server); + if (it != alternate_protocol_map_.end()) + return it; + + CanonicalHostMap::const_iterator canonical = GetCanonicalHost(server); + if (canonical != canonical_host_to_origin_map_.end()) + return alternate_protocol_map_.Get(canonical->second); + + return alternate_protocol_map_.end(); +} + HttpServerPropertiesImpl::CanonicalHostMap::const_iterator HttpServerPropertiesImpl::GetCanonicalHost(HostPortPair server) const { for (size_t i = 0; i < canonical_suffixes_.size(); ++i) {
diff --git a/net/http/http_server_properties_impl.h b/net/http/http_server_properties_impl.h index 5ff6f48f..7a5441c 100644 --- a/net/http/http_server_properties_impl.h +++ b/net/http/http_server_properties_impl.h
@@ -182,6 +182,10 @@ // been marked broken. typedef std::map<HostPortPair, int> BrokenAlternateProtocolMap; + // Return the iterator for |server|, or for its canonical host, or end. + AlternateProtocolMap::const_iterator GetAlternateProtocolIterator( + const HostPortPair& server); + // Return the canonical host for |server|, or end if none exists. CanonicalHostMap::const_iterator GetCanonicalHost(HostPortPair server) const;
diff --git a/net/http/http_util.cc b/net/http/http_util.cc index 9bdc045..5e342270 100644 --- a/net/http/http_util.cc +++ b/net/http/http_util.cc
@@ -405,7 +405,7 @@ std::string::const_iterator name_end) { // NOTE: "set-cookie2" headers do not support expires attributes, so we don't // have to list them here. - const char* kNonCoalescingHeaders[] = { + const char* const kNonCoalescingHeaders[] = { "date", "expires", "last-modified",
diff --git a/net/http/http_util_unittest.cc b/net/http/http_util_unittest.cc index e20bbdce..ee501c7 100644 --- a/net/http/http_util_unittest.cc +++ b/net/http/http_util_unittest.cc
@@ -16,7 +16,7 @@ } TEST(HttpUtilTest, IsSafeHeader) { - static const char* unsafe_headers[] = { + static const char* const unsafe_headers[] = { "sec-", "sEc-", "sec-foo", @@ -53,7 +53,7 @@ EXPECT_FALSE(HttpUtil::IsSafeHeader(StringToUpperASCII(std::string( unsafe_headers[i])))) << unsafe_headers[i]; } - static const char* safe_headers[] = { + static const char* const safe_headers[] = { "foo", "x-", "x-foo", @@ -102,8 +102,8 @@ TEST(HttpUtilTest, HasHeader) { static const struct { - const char* headers; - const char* name; + const char* const headers; + const char* const name; bool expected_result; } tests[] = { { "", "foo", false }, @@ -121,7 +121,7 @@ } TEST(HttpUtilTest, StripHeaders) { - static const char* headers = + static const char* const headers = "Origin: origin\r\n" "Content-Type: text/plain\r\n" "Cookies: foo1\r\n" @@ -130,11 +130,11 @@ "Server: Apache\r\n" "OrIGin: origin2\r\n"; - static const char* header_names[] = { + static const char* const header_names[] = { "origin", "content-type", "cookies" }; - static const char* expected_stripped_headers = + static const char* const expected_stripped_headers = "Custom: baz\r\n" "Server: Apache\r\n"; @@ -262,7 +262,7 @@ TEST(HttpUtilTest, LocateEndOfHeaders) { struct { - const char* input; + const char* const input; int expected_result; } tests[] = { { "foo\r\nbar\r\n\r\n", 12 }, @@ -281,8 +281,8 @@ TEST(HttpUtilTest, AssembleRawHeaders) { struct { - const char* input; // with '|' representing '\0' - const char* expected_result; // with '\0' changed to '|' + const char* const input; // with '|' representing '\0' + const char* const expected_result; // with '\0' changed to '|' } tests[] = { { "HTTP/1.0 200 OK\r\nFoo: 1\r\nBar: 2\r\n\r\n", "HTTP/1.0 200 OK|Foo: 1|Bar: 2||" }, @@ -594,9 +594,9 @@ // Test SpecForRequest() and PathForRequest(). TEST(HttpUtilTest, RequestUrlSanitize) { struct { - const char* url; - const char* expected_spec; - const char* expected_path; + const char* const url; + const char* const expected_spec; + const char* const expected_path; } tests[] = { { // Check that #hash is removed. "http://www.google.com:78/foobar?query=1#hash", @@ -657,11 +657,11 @@ // HttpResponseHeadersTest.GetMimeType also tests ParseContentType. TEST(HttpUtilTest, ParseContentType) { const struct { - const char* content_type; - const char* expected_mime_type; - const char* expected_charset; + const char* const content_type; + const char* const expected_mime_type; + const char* const expected_charset; const bool expected_had_charset; - const char* expected_boundary; + const char* const expected_boundary; } tests[] = { { "text/html; charset=utf-8", "text/html", @@ -741,7 +741,7 @@ TEST(HttpUtilTest, ParseRanges) { const struct { - const char* headers; + const char* const headers; bool expected_return_value; size_t expected_ranges_size; const struct {
diff --git a/net/http/http_vary_data_unittest.cc b/net/http/http_vary_data_unittest.cc index cffa2d29..19dbbd77 100644 --- a/net/http/http_vary_data_unittest.cc +++ b/net/http/http_vary_data_unittest.cc
@@ -32,7 +32,7 @@ TEST(HttpVaryDataTest, IsInvalid) { // All of these responses should result in an invalid vary data object. - const char* kTestResponses[] = { + const char* const kTestResponses[] = { "HTTP/1.1 200 OK\n\n", "HTTP/1.1 200 OK\nVary: *\n\n", "HTTP/1.1 200 OK\nVary: cookie, *, bar\n\n",
diff --git a/net/http/transport_security_state_static.h b/net/http/transport_security_state_static.h index 0d716851..7c0bf746 100644 --- a/net/http/transport_security_state_static.h +++ b/net/http/transport_security_state_static.h
@@ -677,1248 +677,1255 @@ // value has the MSB set then it represents a literal leaf value. Otherwise // it's a pointer to the n'th element of the array. static const uint8 kHSTSHuffmanTree[] = { - 0xe7, 0xf2, 0x00, 0x80, 0xed, 0xae, 0xe9, 0x02, 0xb1, 0xb5, 0xf1, 0x04, + 0xe7, 0xf2, 0xed, 0xae, 0xe9, 0x01, 0x00, 0x02, 0xb1, 0xb5, 0xf1, 0x04, 0xb3, 0xb2, 0x05, 0x06, 0xfa, 0x07, 0xf6, 0x08, 0xeb, 0x09, 0x0a, 0xe3, - 0xe1, 0x0b, 0x03, 0x0c, 0x01, 0x0d, 0xe2, 0xe8, 0x0f, 0xf3, 0xe5, 0x10, + 0xe1, 0x0b, 0x80, 0x0c, 0x03, 0x0d, 0xe2, 0xe8, 0x0f, 0xf3, 0xe5, 0x10, 0xff, 0x11, 0xf4, 0xee, 0xef, 0x13, 0xf7, 0xe4, 0xb9, 0xb7, 0xb6, 0x16, 0xb8, 0x17, 0x18, 0xb0, 0xb4, 0x19, 0x1a, 0xea, 0xf8, 0x1b, 0xad, 0x1c, - 0x1d, 0xf0, 0x15, 0x1e, 0xf9, 0xe6, 0x20, 0xf5, 0x21, 0xec, 0x1f, 0x22, + 0x1d, 0xf0, 0x15, 0x1e, 0xf9, 0xe6, 0xf5, 0x20, 0x21, 0xec, 0x1f, 0x22, 0x14, 0x23, 0x12, 0x24, 0x0e, 0x25, }; static const uint8 kPreloadedHSTSData[] = { - 0xfe, 0x5d, 0x7c, 0x33, 0x00, 0xd1, 0x12, 0xcf, 0xbe, 0x19, 0x80, 0x68, - 0x8b, 0x66, 0xab, 0x4a, 0x93, 0x15, 0x2e, 0xfe, 0x69, 0x7b, 0x16, 0x9f, - 0xda, 0xaf, 0xf6, 0xa4, 0xb9, 0x4b, 0x35, 0x33, 0xf3, 0xf6, 0x8e, 0xa9, - 0xc3, 0xa1, 0x8f, 0xcb, 0x10, 0xe7, 0xf8, 0x5b, 0x68, 0x0c, 0xa4, 0x3a, - 0x4b, 0xa4, 0xd1, 0x7a, 0xa1, 0xe3, 0xe0, 0x82, 0x7f, 0x2e, 0xbe, 0x19, - 0x80, 0x68, 0xa8, 0xa7, 0xff, 0xb6, 0x9b, 0x5f, 0x9a, 0xab, 0x39, 0x6a, - 0xe4, 0xe9, 0xf7, 0xc3, 0x30, 0x0d, 0x15, 0xec, 0xf9, 0x1d, 0x83, 0xdb, - 0x0e, 0x92, 0xe8, 0xf7, 0x3e, 0x63, 0x3f, 0xf2, 0xf1, 0xeb, 0xaf, 0x86, - 0x60, 0x1a, 0x24, 0x69, 0xff, 0xcb, 0x56, 0x3d, 0x75, 0xf0, 0xcc, 0x03, - 0x44, 0xf1, 0x3f, 0xf9, 0x6a, 0xc7, 0xae, 0xbe, 0x19, 0x80, 0x68, 0x9f, - 0xe7, 0xff, 0x2d, 0x58, 0xf5, 0xd7, 0xc3, 0x30, 0x0d, 0x14, 0x34, 0xff, - 0xe5, 0xab, 0x1e, 0xba, 0xf8, 0x66, 0x01, 0xa2, 0x88, 0x9f, 0xf6, 0x3d, - 0x75, 0xf0, 0xcc, 0x03, 0x45, 0x23, 0x3f, 0xff, 0x57, 0x3b, 0x6f, 0x0b, - 0xd0, 0xe7, 0x77, 0xbb, 0x76, 0x54, 0x96, 0xa4, 0x52, 0xf5, 0x23, 0xcf, - 0xfc, 0xbc, 0x7a, 0xeb, 0xe1, 0x98, 0x06, 0x89, 0x42, 0x2c, 0x5d, 0x89, - 0x7c, 0x70, 0x20, 0x81, 0xd7, 0x3c, 0xfc, 0x2b, 0x94, 0x4f, 0xb4, 0xde, - 0xd4, 0xdd, 0xc5, 0x3b, 0xa9, 0xfb, 0x0f, 0x87, 0x62, 0xc9, 0xff, 0xcb, - 0x56, 0x3d, 0x75, 0xf0, 0xcc, 0x03, 0x44, 0xe7, 0x3f, 0xf9, 0x6a, 0xc7, - 0xae, 0xbe, 0x19, 0x80, 0x68, 0xa2, 0x67, 0xfe, 0xfb, 0xd7, 0xb4, 0xbb, - 0x8f, 0x4e, 0xce, 0x8f, 0xa3, 0xb2, 0xea, 0x7e, 0xa9, 0xcf, 0xe5, 0xd7, - 0xc3, 0x30, 0x0d, 0x10, 0xe4, 0xfb, 0xe1, 0x98, 0x06, 0x88, 0xbe, 0x7f, - 0x5e, 0xb9, 0xdd, 0x77, 0x87, 0x4d, 0x7b, 0x4e, 0x9e, 0xd3, 0xdb, 0xc9, - 0x50, 0xa3, 0x75, 0x82, 0xf2, 0x5d, 0x22, 0xf9, 0xc3, 0x11, 0x6d, 0x9f, - 0xfc, 0xb5, 0x63, 0xd7, 0x5f, 0x0c, 0xc0, 0x34, 0x4c, 0x93, 0xf9, 0x75, - 0xf0, 0xcc, 0x03, 0x45, 0xbd, 0x3f, 0xf9, 0x6a, 0xc7, 0xae, 0xbe, 0x19, - 0x80, 0x68, 0xa4, 0xe7, 0xdb, 0x5b, 0xbf, 0xd6, 0xdd, 0xe3, 0xa1, 0x95, - 0x24, 0xbe, 0x1f, 0x54, 0x6b, 0x75, 0x37, 0x47, 0x9e, 0x14, 0xe7, 0xf2, - 0xeb, 0xe1, 0x98, 0x06, 0x88, 0x76, 0x7f, 0xf2, 0xd5, 0x8f, 0x5d, 0x7c, - 0x33, 0x00, 0xd1, 0x2c, 0x4f, 0xe5, 0xd7, 0xc3, 0x30, 0x0d, 0x11, 0x84, - 0xfb, 0xe1, 0x98, 0x06, 0x88, 0xf6, 0x7a, 0xf9, 0x6b, 0xa3, 0xa7, 0x97, - 0x8f, 0x5d, 0x1e, 0xae, 0x8c, 0x67, 0xf2, 0xeb, 0xe1, 0x98, 0x06, 0x8b, - 0x0e, 0x7f, 0x2e, 0xbe, 0x19, 0x80, 0x68, 0xb9, 0xe1, 0x93, 0xd0, 0xb0, - 0xf1, 0xea, 0x69, 0x09, 0x15, 0x1c, 0x68, 0xf2, 0x7f, 0x2e, 0xbe, 0x19, - 0x80, 0x68, 0x87, 0xa7, 0xdf, 0x0c, 0xc0, 0x34, 0x44, 0xd3, 0xff, 0xab, - 0x59, 0xbd, 0xb3, 0xa7, 0xd7, 0xd8, 0xe9, 0xb4, 0xa3, 0xa7, 0xff, 0x56, - 0xfc, 0x59, 0x76, 0x4b, 0x74, 0xca, 0x3a, 0x2d, 0x3e, 0x2d, 0x8b, 0x4f, - 0x6b, 0xdc, 0xf0, 0x68, 0x85, 0xe4, 0xba, 0x4c, 0xc3, 0x66, 0x37, 0x85, - 0x5f, 0xa4, 0x73, 0xbf, 0x80, 0x74, 0xb6, 0x74, 0x79, 0x35, 0x5e, 0x8d, - 0x4f, 0x6b, 0x69, 0xa3, 0xa7, 0xff, 0xfe, 0xdf, 0xbc, 0xa5, 0x7d, 0xc1, - 0xa7, 0x5b, 0xae, 0x5a, 0xf7, 0x6f, 0x27, 0x4f, 0xfe, 0x47, 0x1f, 0x56, - 0xbf, 0xa2, 0xb3, 0x04, 0xe9, 0xb1, 0xd8, 0xe8, 0xa4, 0x7d, 0x81, 0x0e, - 0xdd, 0xf1, 0x2e, 0x77, 0xf0, 0x0e, 0x87, 0x7c, 0xf5, 0x3c, 0x9d, 0x4f, - 0xb7, 0x9a, 0xc7, 0x9d, 0x3f, 0x9f, 0x76, 0xbf, 0x5a, 0xfd, 0x6f, 0xad, - 0x9d, 0x3c, 0x97, 0x4e, 0xce, 0x9d, 0xc7, 0x1c, 0x15, 0x3e, 0xc1, 0xd6, - 0xe8, 0xa5, 0x97, 0xf3, 0xec, 0xd3, 0x95, 0xa3, 0xa3, 0x94, 0x4d, 0xf6, - 0x80, 0x26, 0x93, 0xdb, 0xcc, 0xc3, 0xa7, 0xfe, 0xed, 0x1c, 0xe9, 0xb6, - 0x4f, 0xfb, 0xd7, 0x3a, 0x7f, 0xc9, 0xe5, 0x85, 0xae, 0xc8, 0xa3, 0xa7, - 0xea, 0x75, 0xeb, 0xea, 0xe7, 0x4f, 0x57, 0x35, 0x61, 0xd1, 0x4a, 0x8c, - 0xad, 0x26, 0x48, 0x71, 0xf5, 0xcc, 0x5c, 0x1f, 0xda, 0x60, 0x9e, 0x68, - 0xbe, 0x7e, 0xae, 0x1a, 0xb9, 0x43, 0xa7, 0x37, 0xbd, 0x9d, 0x3f, 0xff, - 0xf8, 0x46, 0xd6, 0xf2, 0x35, 0xce, 0xd1, 0xce, 0x97, 0xab, 0x5f, 0xfa, - 0xe0, 0xe9, 0xf2, 0x6b, 0xd6, 0xb0, 0xe9, 0xff, 0xfd, 0x56, 0xbe, 0xea, - 0xa1, 0xe8, 0xec, 0x9b, 0xb1, 0x2b, 0xe7, 0x4f, 0xff, 0xfb, 0x8e, 0x83, - 0x41, 0xb4, 0x1a, 0xf6, 0xdd, 0x74, 0xce, 0x2b, 0xc9, 0xd3, 0xfa, 0xd7, - 0xdf, 0xcf, 0xad, 0x69, 0xd3, 0xfb, 0x38, 0xf5, 0xc6, 0xd6, 0x1d, 0x0c, - 0x8d, 0xe4, 0x72, 0x13, 0x89, 0xee, 0xf4, 0x96, 0x1d, 0x3f, 0xe6, 0xcb, - 0x19, 0x42, 0xd6, 0xf6, 0x74, 0x32, 0xa7, 0x6a, 0x7d, 0x42, 0x8f, 0xc6, - 0x87, 0x85, 0xa2, 0x47, 0x37, 0xaf, 0x3a, 0x7c, 0xdd, 0xde, 0xcd, 0x1d, - 0x3b, 0x35, 0x73, 0xa6, 0xf6, 0xc3, 0xa7, 0x0e, 0x9c, 0x79, 0xb3, 0xf8, - 0xdc, 0xfd, 0xe8, 0x74, 0xe6, 0xde, 0x0e, 0x86, 0x3e, 0x64, 0x33, 0x9f, - 0xff, 0x7a, 0xda, 0xe8, 0x3e, 0xbb, 0x74, 0xad, 0x75, 0x56, 0x8e, 0x9f, - 0xfb, 0x6d, 0xe7, 0xa6, 0x87, 0x34, 0xda, 0x3a, 0x7f, 0x74, 0xb5, 0xe9, - 0xbf, 0x54, 0x74, 0x76, 0x7f, 0xa2, 0x8d, 0x3f, 0xef, 0xb9, 0xd2, 0xec, - 0x96, 0x66, 0x8e, 0x86, 0x3e, 0x3f, 0x48, 0xa7, 0xff, 0xff, 0xbd, 0x1b, - 0xfc, 0x59, 0xce, 0x9e, 0x34, 0x8f, 0xab, 0x75, 0x4e, 0x86, 0xae, 0x74, - 0x98, 0xe9, 0xfc, 0xfc, 0xfa, 0x5d, 0xad, 0x3a, 0x7f, 0xff, 0xff, 0x27, - 0x77, 0x1a, 0xcb, 0x7a, 0x73, 0xbf, 0x7a, 0x0d, 0x5a, 0xfa, 0xf6, 0xc1, - 0xac, 0xb4, 0xe9, 0xd9, 0x80, 0x68, 0xa6, 0x22, 0x91, 0x78, 0x10, 0x96, - 0x9f, 0xf5, 0x0d, 0xaf, 0xbe, 0x9b, 0xee, 0x1d, 0x3a, 0x93, 0xb3, 0xa5, - 0x47, 0x4e, 0xb4, 0x6b, 0xb3, 0x54, 0xe8, 0x6e, 0x11, 0x13, 0xd8, 0xd3, - 0x39, 0xed, 0x69, 0xd3, 0xf9, 0x5c, 0xed, 0xac, 0xae, 0x0e, 0x8b, 0x4f, + 0xfe, 0x3d, 0x7c, 0x33, 0x01, 0x51, 0x12, 0xcf, 0xbe, 0x19, 0x80, 0xa8, + 0x8b, 0x66, 0xab, 0x52, 0x93, 0x25, 0x2e, 0xfe, 0x69, 0x7b, 0x16, 0x9f, + 0xda, 0xaf, 0xf6, 0x62, 0xba, 0x47, 0x35, 0x33, 0xf3, 0xf6, 0x4e, 0xa9, + 0xc5, 0xa1, 0x8f, 0xcb, 0x10, 0xe7, 0xf8, 0x5b, 0x64, 0x0c, 0x62, 0x5a, + 0x47, 0xa4, 0xd1, 0x7a, 0xa1, 0xe3, 0xe8, 0x82, 0x7f, 0x1e, 0xbe, 0x19, + 0x80, 0xa8, 0xa8, 0xa7, 0xff, 0xb6, 0x5b, 0x3f, 0xba, 0xab, 0x39, 0x6a, + 0xe5, 0x69, 0xf7, 0xc3, 0x30, 0x15, 0x15, 0xec, 0xf8, 0x9d, 0x83, 0xcb, + 0x16, 0x91, 0xe8, 0xf7, 0x3e, 0x63, 0x3f, 0xf1, 0xf1, 0xe7, 0xaf, 0x86, + 0x60, 0x2a, 0x24, 0x69, 0xff, 0xc7, 0x36, 0x3c, 0xf5, 0xf0, 0xcc, 0x05, + 0x44, 0xf1, 0x3f, 0xf8, 0xe6, 0xc7, 0x9e, 0xbe, 0x19, 0x80, 0xa8, 0x9f, + 0xe7, 0xff, 0x1c, 0xd8, 0xf3, 0xd7, 0xc3, 0x30, 0x15, 0x14, 0x34, 0xff, + 0xe3, 0x9b, 0x1e, 0x7a, 0xf8, 0x66, 0x02, 0xa2, 0x88, 0x9f, 0xf6, 0x3c, + 0xf5, 0xf0, 0xcc, 0x05, 0x45, 0x23, 0x3f, 0xff, 0x57, 0x3b, 0x6f, 0x47, + 0xd0, 0xe7, 0x77, 0xbb, 0x76, 0x94, 0x8e, 0x64, 0x52, 0xf5, 0x23, 0xcf, + 0xfc, 0x7c, 0x79, 0xeb, 0xe1, 0x98, 0x0a, 0x89, 0x42, 0x2c, 0x5d, 0x89, + 0x7c, 0x70, 0x20, 0x81, 0xd7, 0x3c, 0xfc, 0x2b, 0x8c, 0x4f, 0xb4, 0xde, + 0xd4, 0xdd, 0xc5, 0x3b, 0xa9, 0xf9, 0x0f, 0x87, 0x62, 0xc9, 0xff, 0xc7, + 0x36, 0x3c, 0xf5, 0xf0, 0xcc, 0x05, 0x44, 0xe7, 0x3f, 0xf8, 0xe6, 0xc7, + 0x9e, 0xbe, 0x19, 0x80, 0xa8, 0xa2, 0x67, 0xfe, 0xfb, 0xcf, 0xb2, 0xbb, + 0x8f, 0x2e, 0xd6, 0x8f, 0xa3, 0xb2, 0xea, 0x7e, 0x29, 0xcf, 0xe3, 0xd7, + 0xc3, 0x30, 0x15, 0x10, 0xe4, 0xfb, 0xe1, 0x98, 0x0a, 0x88, 0xbe, 0x7f, + 0x5e, 0xb9, 0xdd, 0x77, 0x8b, 0x4d, 0x7b, 0x56, 0x9e, 0xd3, 0xdb, 0xda, + 0x50, 0x63, 0x75, 0x82, 0xf2, 0x3d, 0x22, 0xf9, 0xc3, 0x11, 0x6d, 0x9f, + 0xfc, 0x73, 0x63, 0xcf, 0x5f, 0x0c, 0xc0, 0x54, 0x4c, 0x93, 0xf8, 0xf5, + 0xf0, 0xcc, 0x05, 0x45, 0xbd, 0x3f, 0xf8, 0xe6, 0xc7, 0x9e, 0xbe, 0x19, + 0x80, 0xa8, 0xa4, 0xe7, 0xdb, 0x3b, 0xbf, 0xd6, 0xdd, 0xe5, 0xa1, 0x95, + 0x24, 0xbe, 0x1f, 0x54, 0x6b, 0x75, 0x37, 0x47, 0x9e, 0x94, 0xe7, 0xf1, + 0xeb, 0xe1, 0x98, 0x0a, 0x88, 0x76, 0x7f, 0xf1, 0xcd, 0x8f, 0x3d, 0x7c, + 0x33, 0x01, 0x51, 0x2c, 0x4f, 0xe3, 0xd7, 0xc3, 0x30, 0x15, 0x11, 0x84, + 0xfb, 0xe1, 0x98, 0x0a, 0x88, 0xf6, 0x7a, 0xf9, 0x6b, 0xa5, 0xa7, 0x8f, + 0x8f, 0x3d, 0x1e, 0xae, 0x8c, 0x67, 0xf1, 0xeb, 0xe1, 0x98, 0x0a, 0x8b, + 0x0e, 0x7f, 0x1e, 0xbe, 0x19, 0x80, 0xa8, 0xb9, 0xe1, 0x93, 0xd0, 0xb0, + 0xf1, 0xea, 0x65, 0x09, 0x13, 0x1c, 0x68, 0xf2, 0x7f, 0x1e, 0xbe, 0x19, + 0x80, 0xa8, 0x87, 0xa7, 0xdf, 0x0c, 0xc0, 0x54, 0x44, 0xd3, 0xff, 0xab, + 0x59, 0xbd, 0xb3, 0xa7, 0xd7, 0xd9, 0x69, 0xb4, 0x65, 0xa7, 0xff, 0x56, + 0xfd, 0x59, 0x76, 0x2b, 0x74, 0xc6, 0x5a, 0x2d, 0x3e, 0x2d, 0x8b, 0x4f, + 0x6b, 0xcc, 0xf4, 0xa8, 0x85, 0xe4, 0x7a, 0x4c, 0xc3, 0x66, 0x37, 0x85, + 0x5f, 0x84, 0x73, 0xbf, 0x80, 0xb4, 0xb6, 0xb4, 0x7b, 0x35, 0x5e, 0x0d, + 0x4f, 0x6b, 0x65, 0xa5, 0xa7, 0xff, 0xfe, 0xdf, 0x9c, 0x95, 0x7d, 0xc1, + 0xa7, 0x5b, 0xae, 0x5a, 0xf7, 0x6f, 0x6b, 0x4f, 0xfe, 0x27, 0x1f, 0x56, + 0xbf, 0xa1, 0xb3, 0x05, 0x69, 0xb1, 0xd9, 0x68, 0xa4, 0x7d, 0x81, 0x0e, + 0xdd, 0xf1, 0x2e, 0x77, 0xf0, 0x16, 0x87, 0x7c, 0xf5, 0x3d, 0x9d, 0x4f, + 0xb7, 0x9a, 0xc7, 0xad, 0x3f, 0x9f, 0x76, 0xbf, 0x5a, 0xfd, 0x6f, 0xad, + 0xad, 0x3c, 0x57, 0x2e, 0xd6, 0x9d, 0xc7, 0x1c, 0x25, 0x3e, 0xc1, 0xd6, + 0xe9, 0x23, 0x97, 0xf3, 0xec, 0xd3, 0x95, 0xa5, 0xa3, 0x94, 0x4d, 0xf6, + 0x80, 0x26, 0x93, 0xdb, 0xcc, 0xc5, 0xa7, 0xfe, 0xec, 0x9c, 0xe9, 0xb6, + 0x2f, 0xf9, 0xd7, 0x5a, 0x7f, 0xc5, 0xed, 0x85, 0xae, 0xc4, 0x65, 0xa7, + 0xea, 0x75, 0xe3, 0xea, 0xeb, 0x4f, 0x57, 0x35, 0x62, 0xd1, 0x4a, 0x8c, + 0xad, 0x26, 0x28, 0x71, 0xf5, 0xcc, 0x5c, 0x1f, 0xda, 0x60, 0x9e, 0x68, + 0xbe, 0x7e, 0xae, 0x1a, 0xb9, 0x25, 0xa7, 0x37, 0x9d, 0xad, 0x3f, 0xff, + 0xf8, 0x46, 0xd6, 0xf6, 0x35, 0xce, 0xc9, 0xce, 0x97, 0xab, 0x5f, 0xfa, + 0xe1, 0x69, 0xf1, 0x6b, 0xc6, 0xb1, 0x69, 0xff, 0xfd, 0x56, 0xbe, 0xe6, + 0xa1, 0xe8, 0xec, 0x5b, 0xb0, 0xab, 0xeb, 0x4f, 0xff, 0xfb, 0x8e, 0x83, + 0x41, 0xb2, 0x1a, 0xf2, 0xdd, 0x74, 0xce, 0x2b, 0xda, 0xd3, 0xfa, 0xd7, + 0xdf, 0xdf, 0x8d, 0x6a, 0xd3, 0xfb, 0x38, 0xf1, 0xc6, 0xd6, 0x2d, 0x0c, + 0x8d, 0xe2, 0x72, 0x13, 0x89, 0xee, 0xf4, 0x56, 0x2d, 0x3f, 0xe6, 0xcb, + 0x18, 0xc2, 0xd6, 0xf6, 0xb4, 0x32, 0xa7, 0x6a, 0x7d, 0x22, 0x8f, 0xc6, + 0x87, 0x85, 0xa2, 0x47, 0x37, 0x8f, 0x5a, 0x7c, 0xdd, 0xde, 0xcd, 0x2d, + 0x3b, 0x35, 0x75, 0xa6, 0xf2, 0xc5, 0xa7, 0x0e, 0x9c, 0x79, 0xb3, 0xf8, + 0xdc, 0xfd, 0xe0, 0x74, 0xe6, 0xde, 0x16, 0x86, 0x3e, 0x62, 0x33, 0x9f, + 0xff, 0x78, 0xda, 0xe8, 0x3e, 0x3b, 0x74, 0xad, 0x75, 0x56, 0x96, 0x9f, + 0xfb, 0x6d, 0xef, 0xa6, 0x87, 0x34, 0xda, 0x5a, 0x7f, 0x74, 0xb5, 0xe5, + 0xbf, 0x0c, 0xb4, 0x76, 0x7f, 0xa2, 0x8d, 0x3f, 0xef, 0xb9, 0xd2, 0xec, + 0x56, 0x66, 0x96, 0x86, 0x3e, 0x3f, 0x08, 0xa7, 0xff, 0xff, 0xbc, 0x1b, + 0xfc, 0x59, 0xce, 0x9e, 0xb4, 0x4f, 0xab, 0x75, 0x4e, 0x86, 0xae, 0xb4, + 0x99, 0x69, 0xfc, 0xfc, 0xf9, 0x5d, 0xad, 0x5a, 0x7f, 0xff, 0xff, 0x17, + 0x77, 0x1a, 0xcb, 0x7a, 0x73, 0xbf, 0x3a, 0x0d, 0x5a, 0xfa, 0xf2, 0xc1, + 0xac, 0xb5, 0x69, 0xd9, 0x80, 0xa8, 0xa6, 0x22, 0x91, 0x78, 0x10, 0x96, + 0x9f, 0xf5, 0x0d, 0xaf, 0xbe, 0x9b, 0xee, 0x2d, 0x3a, 0x8b, 0xb5, 0xa5, + 0x4b, 0x4e, 0xb4, 0x6b, 0xb3, 0x54, 0xe8, 0x6e, 0x09, 0x13, 0xd8, 0xd3, + 0x39, 0xed, 0x6a, 0xd3, 0xf8, 0xdc, 0xed, 0xac, 0xae, 0x16, 0x8b, 0x4f, 0x47, 0x07, 0x27, 0xff, 0xf0, 0xd0, 0x6b, 0x4d, 0xab, 0xb8, 0x35, 0xc7, - 0x46, 0x77, 0x47, 0x4f, 0xf8, 0x19, 0x5b, 0xab, 0xd2, 0x09, 0xd0, 0xc8, - 0xa1, 0xdb, 0x3c, 0xfb, 0xec, 0xe9, 0xbe, 0x74, 0xfd, 0x83, 0xd3, 0x96, - 0x13, 0xa2, 0x8f, 0xdd, 0x08, 0xbd, 0x28, 0x8b, 0x17, 0x9e, 0x5e, 0x2f, - 0xcc, 0x30, 0xbc, 0x90, 0x04, 0x68, 0x16, 0x91, 0x24, 0x20, 0xdc, 0x0f, - 0xfc, 0x3b, 0x95, 0x0c, 0x41, 0x72, 0xd4, 0x67, 0x53, 0xfe, 0xf3, 0xfc, - 0xe3, 0xa6, 0x73, 0x96, 0x1d, 0x3d, 0x43, 0xe7, 0xae, 0x74, 0xff, 0xff, - 0xfb, 0x69, 0xad, 0xd7, 0xd9, 0xd7, 0x45, 0x7a, 0xed, 0xd2, 0xad, 0x7d, - 0x7a, 0x3d, 0xdc, 0xe9, 0x69, 0x11, 0x6b, 0x72, 0x69, 0xff, 0xf5, 0x56, - 0xd0, 0x37, 0x5d, 0x2f, 0xee, 0xdb, 0xae, 0x74, 0xff, 0xf6, 0xb7, 0x5d, - 0xf4, 0x53, 0x56, 0xb9, 0xa1, 0x3a, 0x7f, 0xad, 0xe8, 0xa6, 0xa1, 0xd7, - 0x51, 0xd2, 0xbd, 0x22, 0x3b, 0x14, 0x64, 0x82, 0x98, 0x76, 0xa1, 0xcf, - 0x3e, 0x7b, 0x5a, 0xfb, 0x9d, 0x3f, 0xff, 0xff, 0xea, 0x1f, 0x3d, 0x13, - 0x7e, 0xad, 0xc4, 0xd3, 0x28, 0x73, 0xce, 0xd1, 0x75, 0xbb, 0x7b, 0x6e, - 0x4a, 0x9f, 0xff, 0xf8, 0x13, 0x8e, 0x7d, 0xff, 0x4f, 0x5a, 0xcb, 0x86, - 0xfd, 0xdd, 0xb9, 0xc1, 0xd3, 0x7b, 0x65, 0xa9, 0xa2, 0x21, 0x45, 0xe1, - 0x43, 0x0c, 0xab, 0xaf, 0x71, 0x9b, 0x0c, 0x6e, 0x33, 0xff, 0x94, 0x1d, - 0x37, 0x8f, 0xa5, 0x60, 0xf6, 0x74, 0xff, 0xf9, 0x07, 0x5b, 0xa7, 0x6d, - 0x39, 0x5d, 0x7c, 0x1e, 0xce, 0x9f, 0xf9, 0x86, 0xc1, 0xa7, 0x57, 0xf5, - 0xad, 0x3a, 0x2e, 0x8a, 0x1f, 0x56, 0xe7, 0xab, 0x54, 0xee, 0x1d, 0x3b, - 0xaa, 0xb6, 0x74, 0xd5, 0xc9, 0xd1, 0x62, 0x6d, 0x0f, 0x87, 0x5d, 0xc9, - 0x34, 0x4a, 0xe8, 0x7a, 0x7c, 0x9a, 0xbd, 0x76, 0x74, 0xfd, 0xcb, 0x0e, - 0xf1, 0xe7, 0x4e, 0x6e, 0x58, 0xe9, 0xf9, 0xf5, 0xab, 0xe3, 0x9d, 0x0f, - 0x1d, 0x45, 0x90, 0xf4, 0x5a, 0xb8, 0xdd, 0x3f, 0x3b, 0x6f, 0x3a, 0xed, - 0xd9, 0xd3, 0xfb, 0xee, 0x0d, 0x6f, 0x34, 0x74, 0x51, 0xf3, 0x21, 0xa4, - 0xfc, 0xdd, 0xd6, 0xbc, 0x58, 0x74, 0x3c, 0xf4, 0x04, 0x82, 0x7f, 0xb5, - 0xba, 0x7e, 0x0d, 0x5a, 0x74, 0xff, 0xff, 0x0e, 0x77, 0x7b, 0x29, 0x07, - 0x43, 0x4e, 0xba, 0x5f, 0x81, 0x3a, 0x05, 0x14, 0x1a, 0x37, 0x9f, 0xf2, - 0x53, 0x9d, 0x2e, 0xdb, 0xce, 0xb9, 0xd3, 0xfb, 0x2d, 0xbe, 0xeb, 0x3e, - 0x74, 0x72, 0x7e, 0xba, 0x43, 0x9f, 0xea, 0xfd, 0x8c, 0x9f, 0xa1, 0x3a, - 0x4a, 0x3b, 0xa1, 0xb6, 0x9c, 0x35, 0xc9, 0xd0, 0xc6, 0xf6, 0xd2, 0x29, - 0xfa, 0xdb, 0xd5, 0x0f, 0x93, 0xa7, 0x95, 0xe1, 0xbb, 0x3a, 0x28, 0xf4, - 0x90, 0xba, 0x77, 0xb6, 0xf6, 0x74, 0x32, 0x7b, 0xf5, 0x09, 0x74, 0x84, - 0xb7, 0xdc, 0xc4, 0x82, 0x7f, 0x69, 0x2c, 0xad, 0xfb, 0xa3, 0xa4, 0xe1, - 0xd3, 0xf5, 0x7b, 0x5b, 0x0b, 0x0e, 0x9a, 0xad, 0x63, 0x7d, 0x71, 0x19, - 0xfb, 0x78, 0xf5, 0x7d, 0x0e, 0x9f, 0x27, 0x7f, 0xab, 0x4e, 0x8f, 0x28, - 0xf2, 0x47, 0x2e, 0xcb, 0x3d, 0x2c, 0x9f, 0xff, 0xbe, 0xfd, 0xd3, 0x9b, - 0x61, 0xf2, 0x35, 0xad, 0xfa, 0x74, 0xff, 0xfe, 0x4a, 0xb5, 0xf7, 0xd6, - 0xd9, 0x4c, 0x9c, 0xf4, 0x67, 0x74, 0x74, 0xff, 0xff, 0xfb, 0xd1, 0xe9, - 0xc6, 0x5a, 0xff, 0xe7, 0x7d, 0x2f, 0xeb, 0x5b, 0xba, 0x41, 0xaf, 0x27, - 0x4f, 0xff, 0xbd, 0xff, 0xeb, 0x57, 0xda, 0x57, 0x4d, 0xf6, 0xc7, 0x45, + 0x46, 0x77, 0x4b, 0x4f, 0xf8, 0x18, 0xdb, 0xab, 0xd1, 0x0a, 0xd0, 0xc8, + 0xa1, 0xdb, 0x3c, 0xfb, 0xec, 0xe9, 0xbe, 0xb4, 0xfd, 0x83, 0xd3, 0x96, + 0x15, 0xa2, 0x8f, 0xdc, 0x88, 0xbc, 0x28, 0x8b, 0x17, 0x9e, 0x5e, 0x2f, + 0xcc, 0x30, 0xbd, 0x90, 0x04, 0x68, 0x16, 0x91, 0x14, 0x20, 0xdc, 0x0f, + 0xfc, 0x3b, 0x8d, 0x0c, 0x41, 0x72, 0xd4, 0x67, 0x53, 0xfe, 0xf7, 0xfc, + 0xe3, 0xa6, 0x73, 0x96, 0x2d, 0x3d, 0x43, 0xef, 0xae, 0xb4, 0xff, 0xff, + 0xfb, 0x65, 0xad, 0xd7, 0xd9, 0xd7, 0x43, 0x78, 0xed, 0xd2, 0xad, 0x7d, + 0x78, 0x3d, 0xdd, 0x69, 0x68, 0x91, 0x6b, 0x72, 0x69, 0xff, 0xf5, 0x56, + 0xc8, 0x37, 0x5d, 0x2f, 0xe6, 0xdb, 0xae, 0xb4, 0xff, 0xf6, 0xb7, 0x5d, + 0xf4, 0x33, 0x56, 0xb9, 0xa1, 0x5a, 0x7f, 0xad, 0xe8, 0x66, 0xa1, 0xd7, + 0x52, 0xd2, 0xbd, 0x22, 0x3b, 0x14, 0x64, 0x42, 0x98, 0x76, 0xa1, 0xcf, + 0x3e, 0x7b, 0x5a, 0xfb, 0xad, 0x3f, 0xff, 0xff, 0xea, 0x1f, 0x7d, 0x0b, + 0x7e, 0x1d, 0xc2, 0xd3, 0x18, 0x73, 0xde, 0xc8, 0xf5, 0xbb, 0x7b, 0x6e, + 0x52, 0x9f, 0xff, 0xf8, 0x0b, 0x8e, 0x7c, 0xff, 0x4f, 0x1a, 0xcb, 0x86, + 0xfc, 0xdd, 0xb9, 0xc2, 0xd3, 0x79, 0x65, 0xa9, 0xa2, 0x11, 0x45, 0xe1, + 0x43, 0x0c, 0xab, 0xaf, 0x71, 0x9b, 0x0c, 0x6e, 0x33, 0xff, 0x8c, 0x1d, + 0x37, 0x8f, 0xa3, 0x60, 0xf6, 0xb4, 0xff, 0xf8, 0x87, 0x5b, 0xa7, 0x6d, + 0x39, 0x5d, 0x7c, 0x1e, 0xd6, 0x9f, 0xf9, 0x86, 0xc1, 0xa7, 0x57, 0xf1, + 0xad, 0x5a, 0x2e, 0x8a, 0x1f, 0x16, 0xe7, 0xab, 0x54, 0xee, 0x2d, 0x3b, + 0xaa, 0xb6, 0xb4, 0xd5, 0xca, 0xd1, 0x62, 0x6d, 0x0f, 0x87, 0x5d, 0xc9, + 0x34, 0x4a, 0xe8, 0x7a, 0x7c, 0x5a, 0xbd, 0x76, 0xb4, 0xfd, 0xcb, 0x0e, + 0xf1, 0xeb, 0x4e, 0x6e, 0x59, 0x69, 0xf9, 0xf5, 0xab, 0xe3, 0x9d, 0x0f, + 0x1c, 0xc5, 0x90, 0xf4, 0x5a, 0xb8, 0xdd, 0x3f, 0x3b, 0x6f, 0x3a, 0xed, + 0xda, 0xd3, 0xfb, 0xee, 0x0d, 0x6f, 0x34, 0xb4, 0x51, 0xf3, 0x11, 0xa4, + 0xfc, 0xdd, 0xd6, 0xbd, 0x58, 0xb4, 0x3c, 0xf4, 0x04, 0x82, 0x7f, 0xb5, + 0xba, 0x7e, 0x0d, 0x5a, 0xb4, 0xff, 0xff, 0x0e, 0x77, 0x7b, 0x28, 0x87, + 0x43, 0x4e, 0xba, 0x5f, 0x81, 0x5a, 0x05, 0x14, 0x1a, 0x37, 0x9f, 0xf1, + 0x53, 0x9d, 0x2e, 0xdb, 0xce, 0xba, 0xd3, 0xfb, 0x2d, 0xbe, 0xeb, 0x3e, + 0xb4, 0x72, 0x7e, 0xba, 0x43, 0x9f, 0xea, 0xfd, 0x8c, 0x5f, 0xa1, 0x5a, + 0x46, 0x5b, 0xa1, 0xb6, 0x9c, 0x35, 0xca, 0xd0, 0xc6, 0xf6, 0xd2, 0x29, + 0xfa, 0xdb, 0xd5, 0x0f, 0xb5, 0xa7, 0x8d, 0xe9, 0xbb, 0x5a, 0x28, 0xf4, + 0x88, 0xba, 0x77, 0x96, 0xf6, 0xb4, 0x32, 0x7b, 0xf5, 0x09, 0x72, 0x84, + 0xb7, 0xdc, 0xc4, 0x82, 0x7f, 0x68, 0xac, 0xad, 0xf9, 0xa5, 0xa4, 0xe2, + 0xd3, 0xf5, 0x79, 0x5b, 0x0b, 0x16, 0x9a, 0xad, 0x63, 0x7d, 0x71, 0x19, + 0xfb, 0x78, 0xf3, 0x7c, 0x96, 0x9f, 0x17, 0x7f, 0xab, 0x56, 0x8f, 0x68, + 0xf2, 0x27, 0x2e, 0xcb, 0x3c, 0x2c, 0x9f, 0xff, 0xbe, 0xfd, 0xd3, 0x9b, + 0x61, 0xf6, 0x35, 0xad, 0xf8, 0xb4, 0xff, 0xfe, 0x2a, 0xb5, 0xf7, 0xd6, + 0xd8, 0xcc, 0x5c, 0xf4, 0x67, 0x74, 0xb4, 0xff, 0xff, 0xfb, 0xc1, 0xe9, + 0xc6, 0x5a, 0xff, 0xe7, 0x7d, 0x2f, 0xe3, 0x5b, 0xba, 0x21, 0xaf, 0x6b, + 0x4f, 0xff, 0xbc, 0xff, 0xeb, 0x57, 0xd9, 0x57, 0x4d, 0xf6, 0xcb, 0x45, 0x23, 0x93, 0x70, 0x8c, 0x9f, 0xfe, 0x7b, 0xb6, 0xe9, 0x85, 0xc1, 0xad, - 0x5f, 0x0e, 0x9f, 0xff, 0x73, 0x4a, 0xe8, 0xed, 0xa6, 0xbb, 0x8f, 0xcf, - 0xd8, 0x74, 0xff, 0x50, 0xd9, 0xd3, 0xbc, 0xc7, 0x0e, 0x9f, 0xef, 0xd8, - 0xd6, 0x59, 0xef, 0xec, 0x3a, 0x7f, 0xbd, 0x1e, 0x97, 0xf7, 0xab, 0xdf, - 0x9d, 0x0c, 0x7f, 0xf7, 0x3e, 0x9f, 0xfd, 0x67, 0x4b, 0xef, 0xde, 0x9a, - 0xbd, 0xdb, 0xe7, 0x4f, 0xff, 0xfa, 0xad, 0xba, 0x57, 0x1d, 0x37, 0x5a, - 0xbd, 0x59, 0xd2, 0x93, 0x93, 0xa2, 0x91, 0x84, 0x8a, 0x31, 0x62, 0xbd, - 0xe0, 0x8d, 0x32, 0xd2, 0x74, 0x50, 0x52, 0xed, 0xe1, 0x75, 0xa8, 0x71, - 0xcf, 0xfb, 0x3f, 0xba, 0xd3, 0x0a, 0x76, 0x74, 0xff, 0x57, 0x16, 0xbe, - 0xfd, 0x34, 0x87, 0x4f, 0xff, 0xf9, 0x81, 0x95, 0xd1, 0xcd, 0xa0, 0xf3, - 0xd3, 0xc0, 0x0d, 0x6e, 0x8e, 0x80, 0x47, 0x38, 0x9e, 0x3b, 0x1e, 0x4f, - 0x26, 0x91, 0x8e, 0x9f, 0xff, 0xfc, 0x29, 0xe7, 0x78, 0xe7, 0x41, 0xf5, - 0xdb, 0xa5, 0x5a, 0xfa, 0xf4, 0x7b, 0xb9, 0xd3, 0xed, 0xa3, 0x0d, 0x87, - 0x4d, 0xa6, 0x52, 0x2a, 0x5d, 0x42, 0x0e, 0x1e, 0x8f, 0xd4, 0x86, 0x44, - 0x32, 0xf7, 0x6d, 0x4e, 0x1d, 0xa4, 0x6b, 0xb9, 0x19, 0x74, 0xf6, 0xaf, - 0x9d, 0x9d, 0x3f, 0xf6, 0xd3, 0xa2, 0x7f, 0xdb, 0x33, 0xe0, 0x74, 0xf2, - 0x6f, 0x2c, 0x3a, 0x79, 0xd3, 0x69, 0x8e, 0x9f, 0xb7, 0x96, 0x74, 0x7e, - 0x8e, 0x9f, 0x67, 0xc6, 0xd4, 0x3a, 0x10, 0xf5, 0xb4, 0x61, 0x14, 0x99, - 0x17, 0x92, 0x20, 0x46, 0x42, 0x1d, 0x3c, 0x4f, 0x78, 0xf7, 0x2e, 0x74, - 0xff, 0xfc, 0x9f, 0xe9, 0x49, 0x43, 0xe7, 0x69, 0x4a, 0xa0, 0x3a, 0x7f, - 0xff, 0x92, 0xcf, 0xb2, 0xaf, 0xeb, 0x74, 0x6f, 0xb7, 0x3b, 0x65, 0x1d, - 0x14, 0x8c, 0x2f, 0xac, 0xcf, 0xff, 0xfe, 0xff, 0xd2, 0xce, 0x9b, 0xad, - 0x0b, 0x39, 0xba, 0xb1, 0xad, 0xd7, 0xa0, 0x74, 0xff, 0xff, 0xcd, 0xe7, - 0x6d, 0xd0, 0x6b, 0xdf, 0x3d, 0x2d, 0x7d, 0xd0, 0x7c, 0x35, 0x87, 0x4f, - 0xad, 0xba, 0x50, 0x9d, 0x14, 0x8a, 0x2f, 0x5f, 0x21, 0x13, 0x41, 0xdc, - 0x63, 0xd3, 0xff, 0x3e, 0xe9, 0xe7, 0x6c, 0x96, 0x37, 0x93, 0xa7, 0xf8, - 0x7d, 0x70, 0x6b, 0x79, 0xa3, 0xa7, 0xfb, 0x9d, 0xb7, 0x1c, 0xef, 0x14, - 0x74, 0xff, 0xff, 0x67, 0xf7, 0x5a, 0x4a, 0x1b, 0x2e, 0xd4, 0x3c, 0xed, - 0x8e, 0x9e, 0xd7, 0x4b, 0x3e, 0x74, 0x5a, 0x88, 0x8c, 0x63, 0x9f, 0xfd, - 0xc6, 0x0d, 0x8a, 0xf5, 0x39, 0x41, 0x43, 0xa7, 0xe7, 0x2d, 0x7f, 0xad, - 0xa3, 0xa7, 0xfb, 0x78, 0xa1, 0xad, 0xe6, 0x8e, 0x9e, 0xaf, 0xf7, 0xc1, - 0xd0, 0xc8, 0x89, 0xb9, 0x86, 0x8d, 0xa7, 0xea, 0xd7, 0xff, 0x4f, 0x3a, - 0x7e, 0x1a, 0xd8, 0xd0, 0x1d, 0x3c, 0x35, 0x7e, 0x8e, 0x1e, 0xae, 0x8b, - 0x23, 0x95, 0xc8, 0x30, 0x8d, 0x8e, 0xd2, 0x94, 0x47, 0xf9, 0xc6, 0xe1, + 0x5f, 0x16, 0x9f, 0xff, 0x73, 0x46, 0xe8, 0xed, 0xa6, 0xbb, 0x8f, 0xcf, + 0xd8, 0xb4, 0xff, 0x50, 0xd9, 0xd3, 0xbc, 0xc7, 0x16, 0x9f, 0xef, 0xd8, + 0xd6, 0x59, 0xe7, 0xec, 0x5a, 0x7f, 0xbc, 0x1e, 0x97, 0xf3, 0xab, 0xcf, + 0xad, 0x0c, 0x7f, 0xf7, 0x3e, 0x9f, 0xfd, 0x67, 0x4b, 0xef, 0xce, 0x9a, + 0xbd, 0xdb, 0xeb, 0x4f, 0xff, 0xfa, 0xad, 0xb9, 0x57, 0x1d, 0x37, 0x5a, + 0xbd, 0x59, 0xd2, 0x8b, 0x95, 0xa2, 0x91, 0x84, 0x4a, 0x31, 0x62, 0xbd, + 0xe0, 0x8d, 0x32, 0xd2, 0x72, 0x50, 0x32, 0xed, 0xe1, 0x75, 0xa8, 0x71, + 0xcf, 0xfb, 0x3f, 0xba, 0xd3, 0x09, 0x76, 0xb4, 0xff, 0x57, 0x16, 0xbe, + 0xfd, 0x34, 0x4b, 0x4f, 0xff, 0xf9, 0x81, 0x8d, 0xd1, 0xcd, 0x90, 0xf3, + 0xd3, 0xd0, 0x0d, 0x6e, 0x96, 0x80, 0x47, 0x38, 0x9e, 0x3b, 0x1e, 0x4f, + 0x16, 0x89, 0x96, 0x9f, 0xff, 0xfc, 0x25, 0xef, 0x78, 0xe7, 0x41, 0xf1, + 0xdb, 0xa5, 0x5a, 0xfa, 0xf0, 0x7b, 0xba, 0xd3, 0xed, 0x93, 0x0d, 0x8b, + 0x4d, 0xa6, 0x32, 0x2a, 0x5d, 0x42, 0x0e, 0x1e, 0x8f, 0xd2, 0x86, 0x44, + 0x32, 0xf7, 0x6d, 0x4e, 0x1d, 0x94, 0x6b, 0xb9, 0x19, 0x74, 0xf6, 0xaf, + 0x9d, 0xad, 0x3f, 0xf6, 0xcb, 0xa1, 0x7f, 0xcb, 0x33, 0xe0, 0xb4, 0xf1, + 0x6f, 0x2c, 0x5a, 0x79, 0xd3, 0x69, 0x96, 0x9f, 0xb7, 0x96, 0x74, 0x7e, + 0x96, 0x9f, 0x67, 0xc6, 0xd2, 0x5a, 0x08, 0xf5, 0xb4, 0x61, 0x14, 0x99, + 0x17, 0xb2, 0x20, 0x46, 0x22, 0x1d, 0x3c, 0x4f, 0x7a, 0xf3, 0x2e, 0xb4, + 0xff, 0xfc, 0x5f, 0xe9, 0x45, 0x43, 0xef, 0x65, 0x46, 0xa0, 0x5a, 0x7f, + 0xff, 0x8a, 0xcf, 0xb1, 0xaf, 0xe3, 0x74, 0x6f, 0xb7, 0x3b, 0x63, 0x2d, + 0x14, 0x8c, 0x2f, 0xac, 0xcf, 0xff, 0xfe, 0xff, 0xca, 0xce, 0x9b, 0xad, + 0x0b, 0x39, 0xba, 0xb1, 0xad, 0xd7, 0x80, 0xb4, 0xff, 0xff, 0xcd, 0xef, + 0x6d, 0xd0, 0x6b, 0xcf, 0x7d, 0x2d, 0x7d, 0xc8, 0x7d, 0x35, 0x8b, 0x4f, + 0xad, 0xb9, 0x50, 0xad, 0x14, 0x8a, 0x2f, 0x1f, 0x20, 0x93, 0x41, 0xdc, + 0x63, 0xd3, 0xff, 0x3e, 0xe5, 0xef, 0x6c, 0x56, 0x37, 0xb5, 0xa7, 0xf8, + 0x7c, 0x70, 0x6b, 0x79, 0xa5, 0xa7, 0xfb, 0x9d, 0xb7, 0x1c, 0xef, 0x0c, + 0xb4, 0xff, 0xff, 0x67, 0xf7, 0x5a, 0x2a, 0x1b, 0x2e, 0xd4, 0x3c, 0xed, + 0x96, 0x9e, 0xd7, 0x4b, 0x3e, 0xb4, 0x5a, 0x88, 0x8c, 0x63, 0x9f, 0xfd, + 0xc6, 0x0d, 0x86, 0xf0, 0xb9, 0x21, 0x25, 0xa7, 0xe7, 0x2d, 0x7f, 0x8d, + 0xa5, 0xa7, 0xfb, 0x78, 0x61, 0xad, 0xe6, 0x96, 0x9e, 0xaf, 0xf7, 0xc2, + 0xd0, 0xc8, 0x89, 0xb9, 0x86, 0x8d, 0xa7, 0xea, 0xd7, 0xff, 0x4f, 0x5a, + 0x7e, 0x1a, 0xd8, 0xd0, 0x2d, 0x3c, 0x35, 0x7e, 0x8e, 0x1e, 0xae, 0x8b, + 0x23, 0x95, 0xc8, 0x30, 0x8d, 0x8e, 0xd2, 0x92, 0x47, 0xf9, 0xc6, 0xe1, 0x87, 0x72, 0x3d, 0x43, 0x4d, 0xd4, 0x21, 0x27, 0xfe, 0x11, 0xae, 0x9f, - 0xad, 0x8d, 0x38, 0x74, 0x32, 0xf2, 0x25, 0x4e, 0xb4, 0xe4, 0x26, 0x27, - 0xc2, 0xca, 0xce, 0x4e, 0x9f, 0xd4, 0xe6, 0xeb, 0x4d, 0xc9, 0xd3, 0xff, - 0xff, 0xdb, 0xad, 0x5f, 0x1c, 0xe8, 0x35, 0x6b, 0xeb, 0xdb, 0x06, 0xb9, - 0xda, 0x38, 0x74, 0xde, 0xf9, 0x3a, 0x3e, 0x89, 0xbd, 0x42, 0x0a, 0x7e, - 0xab, 0x06, 0xad, 0xb9, 0xd3, 0xff, 0xbf, 0x6b, 0xef, 0x4a, 0xb5, 0xb7, - 0xb6, 0x3a, 0x57, 0x3a, 0x3d, 0x3d, 0xbf, 0x09, 0x73, 0xf9, 0x94, 0x35, - 0xbc, 0xd1, 0xd3, 0xdd, 0x02, 0xce, 0x0e, 0x9f, 0xff, 0xf6, 0x85, 0xbb, - 0xb5, 0xf7, 0xf5, 0xb4, 0x35, 0xca, 0x57, 0xdc, 0x3a, 0x11, 0x54, 0x63, - 0x84, 0xd9, 0x0c, 0xe1, 0x28, 0xbc, 0x22, 0x3d, 0x25, 0x74, 0x61, 0xe0, - 0x96, 0x7c, 0xf4, 0xfd, 0x5a, 0x74, 0xfa, 0xaf, 0x65, 0x70, 0x74, 0x5a, - 0x79, 0xfb, 0x27, 0x9f, 0xff, 0x25, 0x94, 0x1c, 0xed, 0x2b, 0xcf, 0x4f, - 0x3e, 0xb1, 0xd3, 0xce, 0xda, 0xad, 0x9d, 0x3f, 0xff, 0xf3, 0xb5, 0xaf, - 0xcb, 0x7a, 0x0f, 0xae, 0xdd, 0x2a, 0xd7, 0xd7, 0xa3, 0xdd, 0xce, 0x8b, - 0x11, 0x4b, 0x44, 0x93, 0xff, 0xff, 0xe6, 0xb6, 0xfe, 0xb5, 0xbd, 0x37, - 0x5c, 0xf4, 0x1a, 0xf7, 0xcf, 0x4b, 0xf7, 0xda, 0x68, 0xe9, 0xf3, 0x0d, - 0xb9, 0x61, 0xd3, 0xff, 0xff, 0xff, 0xa9, 0x54, 0x0d, 0xb6, 0x56, 0xaa, - 0xf7, 0x6f, 0xfd, 0x86, 0xac, 0xaf, 0x6f, 0xeb, 0x82, 0xca, 0x3a, 0x7f, - 0xbb, 0xae, 0x46, 0xb7, 0x9a, 0x3a, 0x7f, 0x59, 0xeb, 0x69, 0x49, 0xa3, - 0xa7, 0xfc, 0xde, 0x5d, 0xbd, 0xa1, 0x73, 0xc2, 0x8e, 0x8a, 0x3f, 0xab, - 0x4d, 0x27, 0xff, 0xab, 0x5c, 0xd5, 0x77, 0x7e, 0x9f, 0xbf, 0x37, 0x3a, - 0x7a, 0xc4, 0x1d, 0x1d, 0x0c, 0xaf, 0xaa, 0x88, 0xd2, 0x30, 0x0f, 0x91, - 0xaa, 0x12, 0x3b, 0x27, 0xc8, 0x51, 0x8c, 0x2c, 0xae, 0x45, 0xea, 0xa4, - 0xee, 0x7a, 0x38, 0x74, 0xff, 0xf5, 0xaf, 0x16, 0xe8, 0xa1, 0x6f, 0x3a, - 0x4b, 0x0e, 0x8a, 0x3f, 0x34, 0x20, 0x9f, 0xac, 0x71, 0xfd, 0x67, 0xec, - 0x3a, 0x7c, 0xa4, 0xe6, 0xb9, 0x3a, 0x4e, 0x1d, 0x33, 0x28, 0xe9, 0x68, - 0xe8, 0xf9, 0xa5, 0xc1, 0x58, 0xe4, 0xf5, 0xb6, 0x6d, 0x3d, 0xab, 0xe5, - 0xa7, 0x4c, 0xe6, 0x1d, 0x3f, 0xb6, 0x9f, 0xb5, 0xe2, 0xc7, 0x47, 0x5b, - 0x4d, 0x05, 0x8d, 0xa9, 0xf9, 0x08, 0xd4, 0x45, 0xe8, 0xb4, 0xfe, 0xba, - 0x5b, 0xc6, 0x0f, 0x67, 0x4f, 0xff, 0x9b, 0xec, 0x14, 0xa6, 0x07, 0xa5, - 0xfd, 0x51, 0xd0, 0xe2, 0x21, 0xba, 0x8d, 0x27, 0xef, 0xd3, 0x79, 0x61, - 0x3a, 0x70, 0xe2, 0x8e, 0x9b, 0xb6, 0x3a, 0x1e, 0x7b, 0x88, 0x58, 0x23, + 0xad, 0x8d, 0x38, 0xb4, 0x32, 0xf2, 0x25, 0x4e, 0xb4, 0xe4, 0x26, 0x27, + 0xc2, 0xc6, 0xce, 0x56, 0x9f, 0xd4, 0xe6, 0xeb, 0x4d, 0xca, 0xd3, 0xff, + 0xff, 0xdb, 0xad, 0x5f, 0x1c, 0xe8, 0x35, 0x6b, 0xeb, 0xcb, 0x06, 0xb9, + 0xd9, 0x38, 0xb4, 0xde, 0x7b, 0x5a, 0x3e, 0x89, 0xbd, 0x42, 0x0a, 0x7e, + 0xab, 0x06, 0xad, 0xba, 0xd3, 0xff, 0xbf, 0x6b, 0xef, 0x46, 0xb5, 0xb7, + 0xb6, 0x5a, 0x57, 0x5a, 0x3c, 0x3d, 0xbf, 0x49, 0x73, 0xf9, 0x8c, 0x35, + 0xbc, 0xd2, 0xd3, 0xdd, 0x02, 0xce, 0x16, 0x9f, 0xff, 0xf6, 0x85, 0xbb, + 0xb5, 0xf7, 0xf1, 0xb4, 0x35, 0xc9, 0x57, 0xdc, 0x5a, 0x09, 0x54, 0x63, + 0x84, 0xd9, 0x0c, 0xe1, 0x28, 0xbc, 0x22, 0x3c, 0x25, 0x74, 0x61, 0xe8, + 0x96, 0x7c, 0xf2, 0xfd, 0x5a, 0xb4, 0xfa, 0xaf, 0x65, 0x70, 0xb4, 0x5a, + 0x79, 0xfb, 0x27, 0x9f, 0xff, 0x15, 0x94, 0x1c, 0xec, 0xab, 0xdf, 0x4f, + 0x7e, 0x32, 0xd3, 0xce, 0xda, 0xad, 0xad, 0x3f, 0xff, 0xf3, 0xb5, 0xaf, + 0xcb, 0x7a, 0x0f, 0x8e, 0xdd, 0x2a, 0xd7, 0xd7, 0x83, 0xdd, 0xd6, 0x8b, + 0x11, 0x4b, 0x44, 0x93, 0xff, 0xff, 0xe6, 0xb6, 0xfe, 0x35, 0xbd, 0x37, + 0x5c, 0xf4, 0x1a, 0xf3, 0xdf, 0x4b, 0xf7, 0xd9, 0x69, 0x69, 0xf3, 0x0d, + 0xb9, 0x62, 0xd3, 0xff, 0xff, 0xff, 0xa8, 0xd4, 0x0d, 0xb6, 0x36, 0xaa, + 0xf7, 0x6f, 0xfd, 0x86, 0xac, 0xaf, 0x2f, 0xe3, 0x82, 0xc6, 0x5a, 0x7f, + 0xbb, 0xae, 0x46, 0xb7, 0x9a, 0x5a, 0x7f, 0x59, 0xe3, 0x68, 0xc5, 0xa5, + 0xa7, 0xfc, 0xde, 0xdd, 0xbc, 0xa1, 0x73, 0xd1, 0x96, 0x8a, 0x3f, 0xab, + 0x4d, 0x27, 0xff, 0xab, 0x5c, 0xd5, 0x77, 0x7e, 0x9f, 0xbf, 0x37, 0x5a, + 0x7a, 0xc2, 0x1d, 0x2d, 0x0c, 0xaf, 0xaa, 0x88, 0xca, 0x30, 0x0f, 0x91, + 0x9a, 0x12, 0x3b, 0x27, 0xc8, 0x51, 0x8c, 0x2c, 0xae, 0x45, 0xe2, 0xa4, + 0xee, 0x7a, 0x38, 0xb4, 0xff, 0xf5, 0xaf, 0x16, 0xe8, 0x61, 0x6f, 0x7a, + 0x2b, 0x16, 0x8a, 0x3f, 0x32, 0x20, 0x9f, 0xac, 0x71, 0xfd, 0x67, 0xec, + 0x5a, 0x7c, 0x62, 0xe6, 0xb9, 0x5a, 0x4e, 0x2d, 0x33, 0x19, 0x69, 0x69, + 0x68, 0xf9, 0xa5, 0xc1, 0x58, 0xe4, 0xf5, 0xb6, 0x6d, 0x3d, 0xab, 0xe5, + 0xab, 0x4c, 0xe6, 0x2d, 0x3f, 0xb6, 0x5f, 0xb5, 0xe2, 0xcb, 0x47, 0x5b, + 0x4d, 0x05, 0x8d, 0xa9, 0xf8, 0x88, 0xcc, 0x45, 0xe0, 0xb4, 0xfe, 0xb9, + 0x5b, 0xc6, 0x0f, 0x6b, 0x4f, 0xff, 0x9b, 0xec, 0x14, 0x66, 0x07, 0x95, + 0xfc, 0x32, 0xd0, 0xe2, 0x21, 0xba, 0x8d, 0x27, 0xef, 0xd3, 0x7b, 0x61, + 0x5a, 0x70, 0xe1, 0x96, 0x9b, 0xb6, 0x5a, 0x1e, 0x7b, 0x84, 0x58, 0x23, 0x50, 0xef, 0x3b, 0x4a, 0x6e, 0xb2, 0x37, 0x36, 0x94, 0xb7, 0x63, 0xdb, - 0xcb, 0x39, 0x95, 0x27, 0x53, 0xda, 0x7e, 0x61, 0x96, 0x12, 0xf9, 0x2d, - 0x8e, 0x91, 0x23, 0x08, 0x72, 0x1b, 0x5f, 0x95, 0x40, 0xa8, 0xd0, 0xf7, + 0xcb, 0x39, 0x95, 0x27, 0x53, 0xda, 0x7e, 0xe1, 0x96, 0x12, 0xf9, 0x2d, + 0x8e, 0x90, 0xa3, 0x08, 0x72, 0x1b, 0x5f, 0x95, 0x40, 0x68, 0xd0, 0xf7, 0x3e, 0x5b, 0x91, 0xb9, 0x0c, 0xf4, 0x75, 0xe5, 0x64, 0xea, 0x72, 0xe5, - 0xd4, 0x62, 0x3d, 0x51, 0xb0, 0xf8, 0x87, 0x13, 0xb4, 0x20, 0xe7, 0xff, - 0xef, 0x41, 0x76, 0xeb, 0xed, 0x56, 0xf5, 0x9c, 0xe6, 0x79, 0x3a, 0x16, - 0xa8, 0xcd, 0x23, 0xcf, 0x9f, 0xcb, 0xaf, 0x86, 0x60, 0x1a, 0x29, 0xd9, - 0xf7, 0xc3, 0x30, 0x0d, 0x15, 0x1c, 0xff, 0xb1, 0xeb, 0xaf, 0x86, 0x60, - 0x1a, 0x26, 0x89, 0x2e, 0x8f, 0xe1, 0x46, 0x33, 0xf9, 0x75, 0xf0, 0xcc, - 0x03, 0x45, 0x5f, 0x3e, 0xf8, 0x66, 0x01, 0xa2, 0xb6, 0x9f, 0xe7, 0xae, - 0xbe, 0x19, 0x80, 0x68, 0x90, 0x64, 0xba, 0x3f, 0x3c, 0x31, 0x9f, 0xf9, - 0x78, 0xf5, 0xd7, 0xc3, 0x30, 0x0d, 0x12, 0x1c, 0xff, 0x9f, 0xb6, 0xd5, - 0xdd, 0xd5, 0xdd, 0xe1, 0x3a, 0x7d, 0x54, 0x3d, 0xdc, 0xe9, 0xf7, 0xc3, - 0x30, 0x0d, 0x16, 0x24, 0xfa, 0xbe, 0xc3, 0xe4, 0xe9, 0xf7, 0x8e, 0xaa, - 0xfb, 0x1d, 0x3a, 0xec, 0x27, 0x4b, 0x6c, 0x78, 0xa8, 0x57, 0x3f, 0xf3, - 0x55, 0xe8, 0x79, 0x4e, 0xd8, 0x4e, 0x9c, 0x2d, 0x61, 0xd2, 0x78, 0x9e, - 0xe7, 0xa8, 0x33, 0xba, 0x93, 0xb3, 0xa7, 0xc8, 0xeb, 0xdc, 0xb9, 0xd3, - 0xff, 0x3a, 0xf6, 0xad, 0xe5, 0xd6, 0xeb, 0x1c, 0x3a, 0x66, 0x79, 0xd1, - 0x47, 0xc1, 0xf4, 0xb9, 0xfd, 0x5f, 0x7f, 0x75, 0x4e, 0x1d, 0x3e, 0xc7, - 0xf8, 0xdb, 0x1d, 0x3f, 0x5e, 0xff, 0x4e, 0x3a, 0xe7, 0x43, 0x22, 0x35, - 0x0c, 0xf0, 0xa2, 0x7f, 0xf9, 0xec, 0xa6, 0x7f, 0x22, 0xdb, 0xca, 0xf9, - 0xd3, 0xf8, 0x06, 0x9d, 0x0d, 0x5c, 0xe8, 0xb4, 0xff, 0xb6, 0x9b, 0x3f, - 0xbb, 0x6a, 0xd2, 0x0f, 0x05, 0x4f, 0xab, 0x76, 0xe7, 0x5c, 0xe9, 0xee, - 0xee, 0xc2, 0x74, 0xfe, 0xfe, 0xf1, 0x2e, 0x8e, 0x8e, 0x86, 0x3d, 0x4a, - 0x21, 0x81, 0x44, 0xfd, 0xdf, 0xe7, 0xec, 0xb3, 0x4d, 0x6b, 0xce, 0x9f, - 0xf0, 0xb2, 0x73, 0xa1, 0xcb, 0x6e, 0x74, 0x3b, 0xcb, 0xa7, 0x1c, 0xa4, - 0xd1, 0x37, 0x93, 0x10, 0x6c, 0xb6, 0x10, 0x48, 0x50, 0xe0, 0xff, 0xe1, - 0x13, 0xb8, 0x57, 0x64, 0x2a, 0xfb, 0x23, 0xbc, 0x34, 0x74, 0x45, 0xe0, - 0xba, 0x7f, 0xed, 0xa3, 0x6b, 0x79, 0xe6, 0x87, 0xb3, 0xa7, 0xff, 0xaa, - 0xd7, 0xeb, 0xdb, 0x17, 0xbc, 0x52, 0x5c, 0xe9, 0xb6, 0xba, 0x44, 0xb0, - 0xa2, 0x42, 0xd3, 0xb4, 0x68, 0xe1, 0xe7, 0xf2, 0xeb, 0xe1, 0x98, 0x06, - 0x8b, 0x36, 0x6a, 0xe4, 0xe9, 0xff, 0x63, 0xd7, 0x5f, 0x0c, 0xc0, 0x34, - 0x50, 0x12, 0x5d, 0x1e, 0xea, 0x85, 0xa6, 0xf7, 0x67, 0x4f, 0xd7, 0x65, - 0x0b, 0x38, 0x74, 0xb6, 0x74, 0xef, 0x02, 0xe1, 0xd3, 0x56, 0xa8, 0xd7, - 0x76, 0x21, 0x1d, 0xa2, 0x18, 0x56, 0xa6, 0xe9, 0x73, 0xa7, 0xfb, 0x75, - 0xfd, 0x0b, 0x2a, 0xe7, 0x4f, 0x06, 0x60, 0x1a, 0x2d, 0xf9, 0xfb, 0xc6, - 0xb0, 0x33, 0xe7, 0x47, 0xcf, 0x63, 0xb2, 0xb9, 0xea, 0x14, 0x70, 0xe9, - 0xf6, 0x9f, 0x7f, 0x17, 0x3a, 0x7e, 0x75, 0xe3, 0x42, 0xdd, 0x9d, 0x3e, - 0xe5, 0xba, 0xfe, 0xa8, 0xe8, 0x63, 0xde, 0x43, 0x19, 0xec, 0x41, 0xd1, - 0xd3, 0xfb, 0xdb, 0x6e, 0xc1, 0x4a, 0x3a, 0x7b, 0x7e, 0x79, 0x51, 0xd3, - 0x53, 0xce, 0x8a, 0x37, 0x42, 0x4b, 0x25, 0xbb, 0xca, 0xbf, 0x5a, 0x13, - 0xaf, 0x23, 0xe4, 0x62, 0xa1, 0x1e, 0x84, 0x7f, 0x20, 0xdc, 0x22, 0x3b, - 0x20, 0x11, 0xfd, 0x36, 0xcf, 0xfb, 0x1e, 0xba, 0xf8, 0x66, 0x01, 0xa2, - 0x94, 0x9f, 0xe7, 0xae, 0xbe, 0x19, 0x80, 0x68, 0x93, 0xa4, 0xb5, 0x22, + 0xd4, 0x62, 0x3d, 0x51, 0xb0, 0xfa, 0x87, 0x13, 0xb4, 0x20, 0xe7, 0xff, + 0xef, 0x00, 0xf6, 0xeb, 0xed, 0x56, 0xf5, 0x9c, 0xe6, 0x7b, 0x5a, 0x0e, + 0xa8, 0xcc, 0xa3, 0xcf, 0x9f, 0xc7, 0xaf, 0x86, 0x60, 0x2a, 0x29, 0xd9, + 0xf7, 0xc3, 0x30, 0x15, 0x15, 0x1c, 0xff, 0xb1, 0xe7, 0xaf, 0x86, 0x60, + 0x2a, 0x26, 0x89, 0x1e, 0x8f, 0xe0, 0xc6, 0x33, 0xf8, 0xf5, 0xf0, 0xcc, + 0x05, 0x45, 0x5f, 0x3e, 0xf8, 0x66, 0x02, 0xa2, 0xb6, 0x9f, 0xe7, 0x9e, + 0xbe, 0x19, 0x80, 0xa8, 0x90, 0x64, 0x7a, 0x3f, 0x3c, 0x31, 0x9f, 0xf8, + 0xf8, 0xf3, 0xd7, 0xc3, 0x30, 0x15, 0x12, 0x1c, 0xff, 0x9f, 0xb6, 0xd5, + 0xdd, 0xd5, 0xdd, 0xe1, 0x5a, 0x7d, 0x54, 0x3d, 0xdd, 0x69, 0xf7, 0xc3, + 0x30, 0x15, 0x16, 0x24, 0xfa, 0xbe, 0xc3, 0xed, 0x69, 0xf7, 0xae, 0xaa, + 0xfb, 0x2d, 0x3a, 0xec, 0x2b, 0x4b, 0x6c, 0x78, 0xa4, 0x57, 0x3f, 0xf3, + 0x55, 0xe8, 0x79, 0x2e, 0xd8, 0x56, 0x9c, 0x2d, 0x62, 0xd2, 0x78, 0x9e, + 0xe7, 0x88, 0x33, 0xba, 0x8b, 0xb5, 0xa7, 0xc4, 0xeb, 0xcc, 0xba, 0xd3, + 0xff, 0x3a, 0xf2, 0xad, 0xe5, 0xd6, 0xeb, 0x1c, 0x5a, 0x66, 0x7a, 0xd1, + 0x47, 0xc1, 0xf4, 0xb9, 0xfd, 0x5f, 0x7f, 0x75, 0x4e, 0x2d, 0x3e, 0xc7, + 0xfa, 0xdb, 0x2d, 0x3f, 0x5e, 0xff, 0x2e, 0x3a, 0xeb, 0x43, 0x22, 0x34, + 0x8c, 0xf0, 0xa2, 0x7f, 0xf9, 0xec, 0x66, 0x7f, 0x22, 0xdb, 0xca, 0xfa, + 0xd3, 0xf8, 0x06, 0x9d, 0x0d, 0x5d, 0x68, 0xb4, 0xff, 0xb6, 0x9b, 0x3f, + 0xbb, 0x6a, 0xd1, 0x0f, 0x09, 0x4f, 0xab, 0x76, 0xe7, 0x5d, 0x69, 0xee, + 0xee, 0xc2, 0xb4, 0xfe, 0xfe, 0xf0, 0xae, 0x4e, 0x96, 0x86, 0x3d, 0x4a, + 0x21, 0x81, 0x44, 0xfd, 0xdf, 0xe7, 0xec, 0xb3, 0x4d, 0x6b, 0xd6, 0x9f, + 0xf0, 0xb1, 0x73, 0xa1, 0xcb, 0x6e, 0xb4, 0x3b, 0xcb, 0xa7, 0x1c, 0xa4, + 0xd1, 0x37, 0xb3, 0x10, 0x6c, 0xb6, 0x10, 0x44, 0x50, 0xe0, 0xff, 0xe1, + 0x13, 0xb8, 0x57, 0x64, 0x2a, 0xfb, 0x23, 0xbc, 0x34, 0x74, 0x45, 0xe8, + 0xba, 0x7f, 0xed, 0x93, 0x6b, 0x79, 0xee, 0x87, 0xb5, 0xa7, 0xff, 0xaa, + 0xd7, 0xeb, 0xcb, 0x0f, 0xbc, 0x31, 0x5d, 0x69, 0xb6, 0x7a, 0x44, 0xb0, + 0xa2, 0x41, 0xd3, 0xb4, 0x68, 0xe1, 0xe7, 0xf1, 0xeb, 0xe1, 0x98, 0x0a, + 0x8b, 0x36, 0x6a, 0xe5, 0x69, 0xff, 0x63, 0xcf, 0x5f, 0x0c, 0xc0, 0x54, + 0x50, 0x12, 0x3d, 0x1e, 0xe9, 0x85, 0xa6, 0xf3, 0x6b, 0x4f, 0xd7, 0x63, + 0x0b, 0x38, 0xb4, 0xb6, 0xb4, 0xef, 0x42, 0xe2, 0xd3, 0x56, 0xa8, 0xd7, + 0x76, 0x21, 0x1d, 0xa2, 0x18, 0x56, 0xa6, 0xe9, 0x75, 0xa7, 0xfb, 0x75, + 0xfd, 0x0b, 0x1a, 0xeb, 0x4f, 0x06, 0x60, 0x2a, 0x2d, 0xf9, 0xfb, 0xd6, + 0xb0, 0x33, 0xeb, 0x47, 0xcf, 0x63, 0xb2, 0xb9, 0xea, 0x12, 0x71, 0x69, + 0xf6, 0x9f, 0x7f, 0x57, 0x5a, 0x7e, 0x75, 0xeb, 0x42, 0xdd, 0xad, 0x3e, + 0xe5, 0xba, 0xfe, 0x19, 0x68, 0x63, 0xde, 0x23, 0x19, 0xec, 0x21, 0xd2, + 0xd3, 0xfb, 0xcb, 0x6e, 0xc1, 0x46, 0x5a, 0x7b, 0x7e, 0xf9, 0x32, 0xd3, + 0x53, 0xd6, 0x8a, 0x37, 0x42, 0x4b, 0x23, 0xbb, 0xca, 0xbf, 0x5a, 0x13, + 0xaf, 0x23, 0xe4, 0x62, 0xa1, 0x1e, 0x44, 0x7f, 0x20, 0xdc, 0x22, 0x3b, + 0x20, 0x11, 0xfd, 0x36, 0xcf, 0xfb, 0x1e, 0x7a, 0xf8, 0x66, 0x02, 0xa2, + 0x94, 0x9f, 0xe7, 0x9e, 0xbe, 0x19, 0x80, 0xa8, 0x93, 0xa4, 0x73, 0x22, 0x27, 0x11, 0xe1, 0x9f, 0x1c, 0x52, 0xc8, 0xdb, 0x39, 0xb6, 0xe9, 0x94, - 0x54, 0x10, 0xb4, 0x42, 0x7e, 0xbc, 0x2b, 0xdc, 0x26, 0x54, 0xf9, 0xce, + 0x54, 0x10, 0xb4, 0x22, 0x7e, 0xbc, 0x2b, 0xdc, 0x26, 0x34, 0xf9, 0xce, 0xca, 0x7b, 0x84, 0xcd, 0xe5, 0x92, 0x3a, 0x8c, 0xee, 0x7d, 0xf0, 0xcc, - 0x03, 0x44, 0x3f, 0x3f, 0xec, 0x7a, 0xeb, 0xe1, 0x98, 0x06, 0x89, 0x4e, - 0x4b, 0xa3, 0xf8, 0x51, 0x8c, 0xfe, 0x5d, 0x7c, 0x33, 0x00, 0xd1, 0x13, - 0xcf, 0xe5, 0xd7, 0xc3, 0x30, 0x0d, 0x11, 0x8c, 0xff, 0xe5, 0xab, 0x1e, - 0xba, 0xf8, 0x66, 0x01, 0xa2, 0x79, 0x86, 0x47, 0x95, 0x84, 0xef, 0x3c, - 0xd9, 0xe4, 0xfb, 0xe1, 0x98, 0x06, 0x88, 0x82, 0x7f, 0xd8, 0xf5, 0xd7, - 0xc3, 0x30, 0x0d, 0x12, 0xa4, 0x97, 0x47, 0xf0, 0xa3, 0x19, 0xfc, 0xba, - 0xf8, 0x66, 0x01, 0xa2, 0x28, 0x9f, 0xcb, 0xaf, 0x86, 0x60, 0x1a, 0x23, - 0x29, 0xff, 0xcb, 0x56, 0x3d, 0x75, 0xf0, 0xcc, 0x03, 0x44, 0xcb, 0x3f, - 0x97, 0x5f, 0x0c, 0xc0, 0x34, 0x54, 0x93, 0xf9, 0x75, 0xf0, 0xcc, 0x03, - 0x45, 0x75, 0x3f, 0x97, 0x5f, 0x0c, 0xc0, 0x34, 0x58, 0xb3, 0xff, 0x2b, - 0x1e, 0xba, 0xf8, 0x66, 0x01, 0xa2, 0x7a, 0x9f, 0xee, 0x17, 0x8c, 0x9d, - 0x48, 0xec, 0x74, 0x2d, 0x11, 0x4c, 0x9b, 0x3f, 0x75, 0xaf, 0x5a, 0x4f, - 0x6e, 0x74, 0xf7, 0xd5, 0xab, 0x4e, 0x9c, 0x15, 0xb2, 0xa7, 0x29, 0xae, - 0x74, 0xff, 0xfd, 0xb1, 0xcf, 0x29, 0xf6, 0x7b, 0xea, 0xfd, 0xf6, 0xc7, - 0x4f, 0xff, 0xdf, 0x47, 0x6c, 0x52, 0xdb, 0xff, 0x47, 0x60, 0xf6, 0xc3, - 0xa7, 0xc0, 0x9b, 0xf0, 0xa3, 0xa7, 0xff, 0x65, 0xc6, 0xbb, 0x5e, 0xd0, - 0x33, 0xe7, 0x4f, 0xb5, 0xb6, 0x50, 0x1d, 0x3f, 0xf8, 0x7a, 0x33, 0x0b, - 0x2b, 0xa7, 0x4d, 0xf5, 0x1d, 0x36, 0x5a, 0x74, 0xfe, 0xcb, 0xe6, 0xfd, - 0x1b, 0x0e, 0x81, 0x3c, 0x9f, 0x45, 0xa2, 0xc5, 0x45, 0x08, 0x37, 0xf5, - 0xc5, 0x30, 0xec, 0xa0, 0x51, 0xf4, 0x4c, 0xed, 0x09, 0x99, 0xc3, 0x9a, - 0x3a, 0x70, 0xa5, 0xce, 0x97, 0x0e, 0xf9, 0xb4, 0x61, 0xa9, 0xef, 0xba, - 0xc5, 0x1d, 0x14, 0x79, 0xe8, 0x59, 0x3f, 0xe4, 0xde, 0x69, 0x9c, 0xba, - 0x28, 0xe9, 0xf0, 0xf9, 0x4a, 0xb9, 0xd3, 0xff, 0x57, 0x19, 0xdd, 0x06, - 0xf3, 0xbb, 0x9d, 0x08, 0x7d, 0x62, 0x4f, 0x39, 0x4d, 0xb3, 0xa7, 0x87, - 0x9e, 0x9e, 0x4e, 0x9f, 0xaa, 0xfc, 0x60, 0xd8, 0x74, 0x51, 0xf7, 0x60, - 0xd8, 0x93, 0x4f, 0xbd, 0xf3, 0x7e, 0x58, 0xe8, 0xa4, 0x72, 0xa4, 0x23, - 0xb6, 0x59, 0x3f, 0xff, 0xfb, 0x6c, 0x9f, 0xfb, 0x78, 0xd2, 0x0f, 0xaf, - 0xab, 0xf3, 0xee, 0x7d, 0xe7, 0x4f, 0xac, 0xe7, 0xe9, 0xc1, 0xd3, 0xf7, - 0x39, 0xfe, 0xfa, 0xa8, 0xe9, 0xff, 0x0a, 0x3f, 0x5b, 0xaf, 0xa5, 0xce, - 0x9f, 0xf6, 0x57, 0x6c, 0x39, 0xcd, 0x79, 0x3a, 0x1e, 0x7f, 0x5d, 0x9e, - 0x4f, 0xec, 0xb6, 0xfa, 0xd5, 0x75, 0xce, 0x9f, 0xfc, 0xd5, 0x6e, 0xb6, - 0xda, 0x16, 0xee, 0xe7, 0x4e, 0xbe, 0xd4, 0x74, 0x68, 0xf9, 0x7d, 0x49, - 0x9f, 0xbd, 0xbe, 0xaf, 0x5a, 0x3a, 0x77, 0x1c, 0x70, 0x54, 0xff, 0xed, - 0x26, 0xaf, 0xb4, 0xea, 0xf1, 0xf6, 0x79, 0x4b, 0x2f, 0xe1, 0x11, 0x55, - 0xea, 0x6c, 0x3d, 0x57, 0xf5, 0x3d, 0x21, 0x57, 0xe1, 0x56, 0xa2, 0x31, - 0x84, 0xe6, 0xa1, 0x9b, 0x3f, 0xd6, 0xbe, 0xf7, 0xae, 0x73, 0x47, 0x4a, - 0x8e, 0x86, 0x3c, 0x9f, 0x27, 0x53, 0xee, 0x34, 0xd6, 0xf0, 0x74, 0xe0, - 0xe3, 0x67, 0x4f, 0xe6, 0xcf, 0xef, 0x8c, 0xe4, 0xa9, 0xb8, 0xe0, 0xa8, - 0xe4, 0xf2, 0xf8, 0x33, 0x9d, 0xa4, 0xeb, 0x94, 0xb3, 0x49, 0x3d, 0xeb, - 0xfd, 0xd1, 0xd1, 0x73, 0xd3, 0xea, 0x2f, 0x9b, 0x8b, 0x9d, 0x2a, 0x3a, + 0x05, 0x44, 0x3f, 0x3f, 0xec, 0x79, 0xeb, 0xe1, 0x98, 0x0a, 0x89, 0x4e, + 0x47, 0xa3, 0xf8, 0x31, 0x8c, 0xfe, 0x3d, 0x7c, 0x33, 0x01, 0x51, 0x13, + 0xcf, 0xe3, 0xd7, 0xc3, 0x30, 0x15, 0x11, 0x8c, 0xff, 0xe3, 0x9b, 0x1e, + 0x7a, 0xf8, 0x66, 0x02, 0xa2, 0x79, 0x86, 0x47, 0x95, 0x84, 0xef, 0x3c, + 0xd9, 0xe4, 0xfb, 0xe1, 0x98, 0x0a, 0x88, 0x82, 0x7f, 0xd8, 0xf3, 0xd7, + 0xc3, 0x30, 0x15, 0x12, 0xa4, 0x8f, 0x47, 0xf0, 0x63, 0x19, 0xfc, 0x7a, + 0xf8, 0x66, 0x02, 0xa2, 0x28, 0x9f, 0xc7, 0xaf, 0x86, 0x60, 0x2a, 0x23, + 0x29, 0xff, 0xc7, 0x36, 0x3c, 0xf5, 0xf0, 0xcc, 0x05, 0x44, 0xcb, 0x3f, + 0x8f, 0x5f, 0x0c, 0xc0, 0x54, 0x54, 0x93, 0xf8, 0xf5, 0xf0, 0xcc, 0x05, + 0x45, 0x75, 0x3f, 0x8f, 0x5f, 0x0c, 0xc0, 0x54, 0x58, 0xb3, 0xff, 0x1b, + 0x1e, 0x7a, 0xf8, 0x66, 0x02, 0xa2, 0x7a, 0x9f, 0xee, 0x0f, 0x8c, 0x5d, + 0x44, 0xec, 0xb4, 0x1d, 0x11, 0x4c, 0x9b, 0x3f, 0x75, 0xaf, 0x5a, 0x2f, + 0x2e, 0xb4, 0xf7, 0xcd, 0xab, 0x56, 0x9c, 0x15, 0xb4, 0xa7, 0x19, 0xae, + 0xb4, 0xff, 0xfd, 0xb1, 0xcf, 0x65, 0xf6, 0x7b, 0xea, 0xfd, 0xf6, 0xcb, + 0x4f, 0xff, 0xdf, 0x27, 0x6c, 0x31, 0xdb, 0xff, 0x27, 0x60, 0xf2, 0xc5, + 0xa7, 0xc0, 0x5b, 0xf4, 0x65, 0xa7, 0xff, 0x65, 0xc6, 0xbb, 0x3e, 0xc8, + 0x33, 0xeb, 0x4f, 0xb5, 0xb6, 0x30, 0x2d, 0x3f, 0xf8, 0x7a, 0x33, 0x0b, + 0x1b, 0xa7, 0x4d, 0xf5, 0x2d, 0x36, 0x5a, 0xb4, 0xfe, 0xcb, 0xe6, 0xfc, + 0x1b, 0x16, 0x81, 0x3c, 0x9f, 0x05, 0xa2, 0xc5, 0x45, 0x04, 0x37, 0xf5, + 0xc3, 0x30, 0xec, 0xa0, 0x51, 0xf4, 0x4c, 0xed, 0x09, 0x99, 0xc3, 0x9a, + 0x5a, 0x70, 0x95, 0xd6, 0x97, 0x0e, 0xf9, 0xb4, 0x61, 0xa9, 0xef, 0xba, + 0xc3, 0x2d, 0x14, 0x79, 0xe4, 0x59, 0x3f, 0xe2, 0xde, 0x69, 0x9c, 0xb9, + 0x19, 0x69, 0xf0, 0xfb, 0x2a, 0xba, 0xd3, 0xff, 0x57, 0x19, 0xdd, 0x06, + 0xf3, 0xbb, 0xad, 0x04, 0x7d, 0x62, 0x4f, 0x38, 0xcd, 0xb5, 0xa7, 0x87, + 0x9e, 0x9e, 0xd6, 0x9f, 0xaa, 0xfc, 0x60, 0xd8, 0xb4, 0x51, 0xf7, 0x60, + 0xd8, 0x93, 0x4f, 0xbc, 0xf7, 0x7e, 0x59, 0x68, 0xa4, 0x72, 0x94, 0x23, + 0xb6, 0x59, 0x3f, 0xff, 0xfb, 0x6c, 0x5f, 0xfb, 0x7a, 0xd1, 0x0f, 0x8f, + 0xab, 0xf3, 0xe6, 0x7d, 0xeb, 0x4f, 0xac, 0xe7, 0xe5, 0xc2, 0xd3, 0xf7, + 0x39, 0xfe, 0xfa, 0xa9, 0x69, 0xff, 0x09, 0x3f, 0x5b, 0xaf, 0x95, 0xd6, + 0x9f, 0xf6, 0x57, 0x6c, 0x39, 0xcd, 0x7b, 0x5a, 0x1e, 0x7f, 0x5d, 0x9e, + 0x4f, 0xec, 0xb6, 0xfa, 0xd5, 0x75, 0xd6, 0x9f, 0xfc, 0xd5, 0x6e, 0xb6, + 0xda, 0x16, 0xee, 0xeb, 0x4e, 0xbe, 0xcc, 0xb4, 0x68, 0xf9, 0x7c, 0x49, + 0x9f, 0xbc, 0xbe, 0xaf, 0x5a, 0x5a, 0x77, 0x1c, 0x70, 0x94, 0xff, 0xed, + 0x16, 0xaf, 0xb2, 0xea, 0xf5, 0xf6, 0x7a, 0x47, 0x2f, 0xe0, 0x91, 0x55, + 0xe2, 0x6c, 0x3d, 0x57, 0xf5, 0x3d, 0x11, 0x57, 0xe1, 0x56, 0x62, 0x31, + 0x84, 0xe6, 0xa1, 0x9b, 0x3f, 0xd6, 0xbe, 0xf7, 0xae, 0x73, 0x4b, 0x4a, + 0x96, 0x86, 0x3c, 0x9f, 0x67, 0x53, 0xee, 0x34, 0xd6, 0xf0, 0xb4, 0xe0, + 0xe3, 0x6b, 0x4f, 0xe6, 0xcf, 0xef, 0x8c, 0xe5, 0x29, 0xb8, 0xe1, 0x28, + 0xe4, 0xf2, 0xf8, 0x33, 0x9d, 0xa2, 0xeb, 0xa4, 0x73, 0x49, 0x3d, 0xe3, + 0xfc, 0xd2, 0xd1, 0x73, 0xd3, 0xea, 0x2f, 0x9b, 0x8b, 0xad, 0x2a, 0x5a, 0x56, 0xd1, 0xa6, 0xd0, 0xbc, 0xff, 0xd7, 0xbf, 0x22, 0xdc, 0xed, 0xb5, - 0x73, 0xa1, 0x8f, 0xb3, 0xd2, 0x79, 0xff, 0x69, 0x3f, 0x9d, 0xbb, 0x6a, - 0xb6, 0x74, 0xfe, 0xcf, 0xea, 0xe2, 0x9e, 0x4e, 0x87, 0xa2, 0x59, 0x08, - 0xb1, 0x06, 0x75, 0x27, 0xce, 0x9e, 0xcf, 0xb3, 0xce, 0x8b, 0x0d, 0xd2, - 0x86, 0xa7, 0xfc, 0xd6, 0xed, 0x94, 0x1b, 0x47, 0x0e, 0x8a, 0x3e, 0x0f, - 0x91, 0x4f, 0xda, 0x6f, 0xf3, 0x42, 0x74, 0xfe, 0xe7, 0x6c, 0x3c, 0x65, - 0xa7, 0x4f, 0xfc, 0x9c, 0xed, 0x81, 0xbb, 0xc1, 0xec, 0xe9, 0xff, 0xff, - 0x22, 0xb0, 0x6d, 0x7a, 0xf8, 0xa4, 0x75, 0x43, 0x5c, 0xe3, 0xcf, 0x17, - 0xac, 0x32, 0x63, 0x98, 0x59, 0x73, 0x4f, 0x50, 0xe7, 0xff, 0xab, 0x57, - 0xa7, 0x36, 0xce, 0xab, 0x7b, 0x63, 0xa7, 0xff, 0xff, 0xc9, 0x56, 0xdd, - 0x2b, 0x8e, 0x95, 0x6b, 0xee, 0x9a, 0xba, 0x5b, 0xcf, 0x3e, 0xd8, 0x74, - 0xff, 0xf9, 0x07, 0x9e, 0x9e, 0x34, 0x97, 0xc4, 0x1f, 0x5e, 0x74, 0x0a, - 0x66, 0x7a, 0x50, 0x75, 0x08, 0xb9, 0xb3, 0x93, 0xa7, 0xef, 0xe5, 0xf7, - 0x8f, 0x3a, 0x56, 0x9d, 0x32, 0x70, 0x74, 0xde, 0x3b, 0x3a, 0x1c, 0x35, - 0xfd, 0x8b, 0x4e, 0x7e, 0x72, 0x74, 0xdc, 0x70, 0x74, 0x3d, 0x1b, 0x34, - 0x2c, 0x05, 0x88, 0x81, 0x72, 0x3e, 0x07, 0x27, 0x6b, 0xc7, 0x65, 0x2c, - 0xf5, 0x67, 0xff, 0xff, 0x69, 0xb9, 0xdf, 0xb9, 0xe5, 0x59, 0xcd, 0x50, - 0xf9, 0xbd, 0xe8, 0x7b, 0x3a, 0x2d, 0x45, 0x62, 0x18, 0x4f, 0xf5, 0x6b, - 0x6d, 0xfd, 0x50, 0x1d, 0x39, 0xbe, 0xe1, 0xd1, 0x4a, 0xa1, 0xb2, 0x50, - 0x88, 0x91, 0xf5, 0x1b, 0x4e, 0xbe, 0x38, 0x74, 0xf5, 0x6b, 0x1d, 0x8e, - 0x8b, 0x4d, 0xf8, 0x8e, 0x4f, 0xfd, 0x5f, 0xfd, 0x39, 0xba, 0xbe, 0x09, - 0xd3, 0xf8, 0x5b, 0xfe, 0x86, 0xd8, 0xe9, 0xf2, 0x79, 0xde, 0x3c, 0xe9, - 0xf9, 0x19, 0x56, 0x57, 0x07, 0x4d, 0xc7, 0x07, 0x40, 0x1f, 0x6f, 0xca, - 0x38, 0x2d, 0x9f, 0xea, 0x73, 0x1c, 0xcb, 0x5f, 0x72, 0x96, 0x6b, 0xe7, - 0xfa, 0xab, 0xba, 0x71, 0xad, 0xb9, 0xd3, 0xff, 0xa8, 0x7b, 0xad, 0xa5, - 0xb7, 0xdf, 0xb7, 0x3a, 0x7e, 0x1c, 0xef, 0x9a, 0x13, 0xa7, 0xe5, 0x27, - 0x55, 0x7f, 0xc9, 0xd3, 0xb8, 0xe3, 0x82, 0xa7, 0xfe, 0x6f, 0x8f, 0xb9, - 0xe2, 0x9c, 0x65, 0x1c, 0xb2, 0xfe, 0x3a, 0xea, 0x9a, 0xdc, 0x86, 0x68, - 0xa5, 0x5c, 0xe7, 0x49, 0x7e, 0x96, 0x70, 0xa1, 0x3f, 0xfe, 0xce, 0x6a, - 0x87, 0xcf, 0x81, 0x61, 0xb1, 0x3e, 0x74, 0xec, 0xfd, 0x87, 0x90, 0x4a, - 0x79, 0xf5, 0x6b, 0xcf, 0x20, 0x94, 0xeb, 0xa7, 0x27, 0x90, 0x4a, 0x6e, - 0x38, 0x3c, 0x82, 0x50, 0x08, 0xa6, 0x70, 0xa7, 0x45, 0xfc, 0x14, 0xcd, - 0x9a, 0x2c, 0x82, 0x45, 0x9b, 0xe9, 0xfa, 0xb7, 0x54, 0x3e, 0x4e, 0x9d, - 0x83, 0xda, 0x93, 0x99, 0x18, 0xce, 0xb4, 0x67, 0x3d, 0xd5, 0x59, 0xb3, - 0xa5, 0x5d, 0x73, 0xea, 0xed, 0x1e, 0x7f, 0x38, 0xff, 0x6c, 0xd2, 0x58, - 0x54, 0xfe, 0x47, 0xfb, 0x97, 0xda, 0x1d, 0x27, 0x95, 0x3b, 0x3f, 0x61, - 0x50, 0x54, 0x31, 0xb6, 0x01, 0x05, 0x0e, 0x4f, 0x0b, 0x76, 0x05, 0x2c, - 0xd6, 0x43, 0x23, 0x12, 0xa1, 0x29, 0x3d, 0xee, 0x7d, 0xe7, 0x49, 0x47, - 0x4d, 0x4f, 0xe4, 0xd9, 0x38, 0x45, 0x3e, 0xe2, 0x9c, 0x45, 0x1d, 0x3f, - 0x03, 0x38, 0xf6, 0xec, 0xa9, 0x21, 0xd3, 0xfd, 0x67, 0xaf, 0xe7, 0x7e, - 0xe0, 0x9d, 0x3f, 0x23, 0x2a, 0xca, 0xe0, 0xe9, 0xf5, 0x58, 0xaa, 0x51, - 0xd3, 0xae, 0x9f, 0x3a, 0x04, 0xf0, 0xb4, 0x4f, 0x3f, 0x0e, 0x77, 0xdf, - 0xb7, 0x3a, 0x7e, 0x4f, 0x3e, 0x19, 0x4b, 0xe5, 0x30, 0xaa, 0x0f, 0xf9, - 0xe5, 0xdb, 0xf4, 0x43, 0x14, 0x9e, 0x82, 0x14, 0x0c, 0x66, 0xf3, 0xc3, - 0x56, 0x7a, 0x74, 0x3d, 0x5e, 0x9d, 0x16, 0x6e, 0x1f, 0x62, 0xb1, 0x78, - 0xff, 0xb4, 0x69, 0x3f, 0xfe, 0xb3, 0xff, 0xae, 0x71, 0x5b, 0xcd, 0x0b, - 0x38, 0x74, 0xff, 0xff, 0xef, 0x7f, 0xeb, 0x83, 0x9d, 0xde, 0xf5, 0xe6, - 0xbd, 0xfe, 0x72, 0xdb, 0x63, 0xa7, 0x71, 0xc7, 0x05, 0x4c, 0xf6, 0x29, - 0x65, 0xfc, 0x32, 0x62, 0xd6, 0x2b, 0x7e, 0x13, 0x93, 0xf5, 0x8e, 0x3f, - 0xac, 0xfd, 0x87, 0x4f, 0x6f, 0x2d, 0xe0, 0xe9, 0xf5, 0x9f, 0x46, 0x51, - 0xd3, 0xff, 0xcd, 0xe3, 0x42, 0xdd, 0xe6, 0xbb, 0xf0, 0x2f, 0x3a, 0x3a, - 0xda, 0x34, 0xd0, 0xdb, 0x08, 0xf4, 0x4f, 0x3b, 0xc7, 0x2e, 0x1d, 0x39, - 0xe8, 0x27, 0x4f, 0xda, 0x67, 0x07, 0xdb, 0x9d, 0x16, 0x1f, 0x43, 0xc8, - 0x34, 0x35, 0x36, 0x5c, 0xe9, 0xbd, 0x77, 0x0e, 0x81, 0x36, 0x3e, 0x8a, - 0xcd, 0x8b, 0x77, 0x9b, 0xee, 0xa7, 0x76, 0x6d, 0xd6, 0xb1, 0x1b, 0x4a, - 0x42, 0xb2, 0x1f, 0xaf, 0x20, 0xe6, 0x38, 0xda, 0x96, 0x63, 0xe6, 0x17, - 0x60, 0x47, 0x69, 0x52, 0x43, 0x79, 0xc8, 0xd3, 0x7f, 0x0c, 0x85, 0x46, + 0x75, 0xa1, 0x8f, 0xb3, 0xc2, 0x79, 0xff, 0x68, 0xbf, 0x9d, 0xbb, 0x6a, + 0xb6, 0xb4, 0xfe, 0xcf, 0xea, 0xe2, 0x5e, 0xd6, 0x87, 0xa2, 0x58, 0x88, + 0xb1, 0x06, 0x75, 0x17, 0xd6, 0x9e, 0xcf, 0xb3, 0xd6, 0x8b, 0x0d, 0xd1, + 0x86, 0xa7, 0xfc, 0xd6, 0xed, 0x8c, 0x1b, 0x27, 0x16, 0x8a, 0x3e, 0x0f, + 0x91, 0x4f, 0xda, 0x6f, 0xf3, 0x42, 0xb4, 0xfe, 0xe7, 0x6c, 0x3c, 0x65, + 0xab, 0x4f, 0xfc, 0x5c, 0xed, 0x81, 0xbb, 0xc1, 0xed, 0x69, 0xff, 0xff, + 0x11, 0xb0, 0x6d, 0x79, 0xf8, 0xa2, 0x75, 0x43, 0x5c, 0xe3, 0xd7, 0x17, + 0xac, 0x32, 0x63, 0x98, 0x59, 0x73, 0x4f, 0x10, 0xe7, 0xff, 0xab, 0x57, + 0xa7, 0x36, 0xce, 0xab, 0x7b, 0x65, 0xa7, 0xff, 0xff, 0xc5, 0x56, 0xdc, + 0xab, 0x8e, 0x95, 0x6b, 0xee, 0x5a, 0xb9, 0x5b, 0xcf, 0x3e, 0x58, 0xb4, + 0xff, 0xf8, 0x87, 0x9e, 0x9e, 0xb4, 0x57, 0xc2, 0x1f, 0x1e, 0xb4, 0x0a, + 0x66, 0x7a, 0x50, 0x75, 0x08, 0xb9, 0xb3, 0x95, 0xa7, 0xef, 0xe5, 0xf7, + 0x8f, 0x5a, 0x56, 0xad, 0x31, 0x70, 0xb4, 0xde, 0xbb, 0x5a, 0x1c, 0x35, + 0xfd, 0x8b, 0x4e, 0x7e, 0x72, 0xb4, 0xdc, 0x70, 0xb4, 0x3d, 0x1b, 0x34, + 0x2c, 0x05, 0x84, 0x81, 0x72, 0x3e, 0x07, 0x27, 0x6b, 0xd7, 0x69, 0x1c, + 0xf5, 0x67, 0xff, 0xff, 0x69, 0xb9, 0xdf, 0x99, 0xec, 0xd9, 0xcd, 0x50, + 0xfb, 0xbd, 0xe8, 0x7b, 0x5a, 0x2d, 0x45, 0x61, 0x18, 0x4f, 0xf5, 0x6b, + 0x6d, 0xfd, 0x50, 0x2d, 0x39, 0xbe, 0xe2, 0xd1, 0x4a, 0xa1, 0xb2, 0x50, + 0x88, 0x91, 0xf5, 0x1b, 0x4e, 0xbe, 0x38, 0xb4, 0xf5, 0x6b, 0x1d, 0x96, + 0x8b, 0x4d, 0xf8, 0x8e, 0x4f, 0xfd, 0x5f, 0xfd, 0x39, 0xba, 0xbe, 0x0a, + 0xd3, 0xf8, 0x5b, 0xfe, 0x06, 0xd9, 0x69, 0xf1, 0x7b, 0xde, 0x3d, 0x69, + 0xf8, 0x98, 0xd6, 0x57, 0x0b, 0x4d, 0xc7, 0x0b, 0x40, 0x1f, 0x6f, 0xca, + 0x38, 0x2d, 0x9f, 0xea, 0x73, 0x1c, 0xcb, 0x5f, 0x74, 0x8e, 0x6b, 0xe7, + 0xfa, 0xab, 0xba, 0x71, 0xad, 0xba, 0xd3, 0xff, 0xa8, 0x7b, 0xad, 0x95, + 0xb7, 0xdf, 0x97, 0x5a, 0x7e, 0x1c, 0xef, 0x9a, 0x15, 0xa7, 0xe3, 0x17, + 0x55, 0x7f, 0xda, 0xd3, 0xb8, 0xe3, 0x84, 0xa7, 0xfe, 0x6f, 0x8f, 0x99, + 0xea, 0x9c, 0x63, 0x2c, 0x72, 0xfe, 0x3a, 0xea, 0x9a, 0xdc, 0x86, 0x68, + 0xa5, 0x5c, 0xe7, 0x49, 0x7e, 0x16, 0x70, 0xa1, 0x3f, 0xfe, 0xce, 0x6a, + 0x87, 0xdf, 0xa1, 0x61, 0xb0, 0xbe, 0xb4, 0xec, 0xfd, 0x8b, 0x90, 0x4a, + 0x79, 0xf5, 0x6b, 0xd7, 0x20, 0x94, 0xeb, 0x97, 0x2b, 0x90, 0x4a, 0x6e, + 0x38, 0x5c, 0x82, 0x50, 0x08, 0xa6, 0x70, 0xa7, 0x45, 0xfc, 0x14, 0xcd, + 0x9a, 0x4c, 0x82, 0x43, 0x9b, 0xe9, 0xfa, 0xb7, 0x54, 0x3e, 0xd6, 0x9d, + 0x83, 0xd9, 0x93, 0x99, 0x18, 0xce, 0xb4, 0x67, 0x3d, 0xd5, 0x59, 0xb5, + 0xa5, 0x5d, 0x73, 0xea, 0xed, 0x1e, 0x7f, 0x38, 0xff, 0x2c, 0xd1, 0x58, + 0x94, 0xfe, 0x27, 0xf9, 0x97, 0xd9, 0x2d, 0x27, 0xa5, 0x3b, 0x3f, 0x62, + 0x50, 0x94, 0x31, 0xb6, 0x01, 0x03, 0x0e, 0x4f, 0x0b, 0x76, 0x09, 0x1c, + 0xd6, 0x43, 0x23, 0x12, 0xa1, 0x29, 0x3d, 0xe6, 0x7d, 0xeb, 0x48, 0xcb, + 0x4d, 0x4f, 0xe4, 0xd9, 0x38, 0x45, 0x3e, 0xe2, 0x9c, 0x23, 0x2d, 0x3f, + 0x03, 0x38, 0xf6, 0xed, 0x29, 0x12, 0xd3, 0xfd, 0x67, 0x8f, 0xe7, 0x7e, + 0x60, 0xad, 0x3f, 0x13, 0x1a, 0xca, 0xe1, 0x69, 0xf5, 0x58, 0x6a, 0x32, + 0xd3, 0xae, 0x5f, 0x5a, 0x04, 0xf0, 0xb4, 0x4f, 0x3f, 0x0e, 0x77, 0xdf, + 0x97, 0x5a, 0x7e, 0x2f, 0x7e, 0x98, 0xc7, 0xe5, 0x30, 0xaa, 0x0f, 0xf9, + 0xe5, 0xdb, 0xf4, 0x43, 0x14, 0x9e, 0x81, 0x14, 0x0c, 0x66, 0xf3, 0xc3, + 0x56, 0x78, 0xb4, 0x3d, 0x5e, 0x9d, 0x16, 0x6e, 0x1f, 0x62, 0xb1, 0x78, + 0xff, 0xb4, 0x69, 0x3f, 0xfe, 0xb3, 0xff, 0xae, 0x70, 0xdb, 0xcd, 0x0b, + 0x38, 0xb4, 0xff, 0xff, 0xef, 0x3f, 0xe3, 0x83, 0x9d, 0xde, 0xf5, 0xee, + 0xbc, 0xfe, 0x72, 0xdb, 0x65, 0xa7, 0x71, 0xc7, 0x09, 0x4c, 0xf6, 0x48, + 0xe5, 0xfc, 0x32, 0x62, 0xd6, 0x2b, 0x7e, 0x13, 0x93, 0xf5, 0x8e, 0x3f, + 0xac, 0xfd, 0x8b, 0x4f, 0x6f, 0x2d, 0xe1, 0x69, 0xf5, 0x9f, 0x26, 0x32, + 0xd3, 0xff, 0xcd, 0xeb, 0x42, 0xdd, 0xe6, 0xbb, 0xf4, 0x2f, 0x5a, 0x3a, + 0xda, 0x34, 0xc8, 0xdb, 0x08, 0xf4, 0x4f, 0x3b, 0xd7, 0x2e, 0x2d, 0x39, + 0xe4, 0x2b, 0x4f, 0xda, 0x67, 0x07, 0xcb, 0xad, 0x16, 0x1f, 0x43, 0xc8, + 0x34, 0x35, 0x36, 0x5d, 0x69, 0xbc, 0x77, 0x16, 0x81, 0x36, 0x3e, 0x0a, + 0xcd, 0x87, 0x77, 0x9b, 0xee, 0xa7, 0x76, 0x6d, 0xd6, 0xb1, 0x1b, 0x4a, + 0x42, 0xb2, 0x1f, 0xaf, 0x20, 0xe6, 0x38, 0xda, 0x96, 0x63, 0xee, 0x17, + 0x60, 0x47, 0x69, 0x51, 0x43, 0x79, 0xc8, 0xd3, 0x7f, 0x0c, 0x83, 0x46, 0x7b, 0xb9, 0x7e, 0xd9, 0x08, 0x51, 0x21, 0xbc, 0xaa, 0xdd, 0x4f, 0x23, - 0xfb, 0x1b, 0xc7, 0x54, 0x61, 0x3e, 0x21, 0x52, 0xec, 0xc3, 0x3f, 0xf9, - 0x6a, 0xc7, 0xae, 0xbe, 0x19, 0x80, 0x68, 0xa2, 0xa7, 0xf2, 0xeb, 0xe1, - 0x98, 0x06, 0x8b, 0xa2, 0x7f, 0xe5, 0xe3, 0xd7, 0x5f, 0x0c, 0xc0, 0x34, - 0x49, 0x73, 0xf9, 0x75, 0xf0, 0xcc, 0x03, 0x45, 0xe5, 0x0c, 0xe9, 0x08, - 0xac, 0x27, 0x79, 0xe5, 0x1e, 0x02, 0x9b, 0x87, 0x8a, 0x3c, 0xdc, 0x31, - 0x86, 0xbf, 0x0c, 0xbc, 0x79, 0xda, 0x53, 0xf4, 0xf1, 0xd2, 0x6c, 0xff, - 0xe5, 0xab, 0x1e, 0xba, 0xf8, 0x66, 0x01, 0xa2, 0x59, 0x9b, 0xdd, 0x9d, - 0x3c, 0x19, 0x80, 0x68, 0x8c, 0xe7, 0xe4, 0x65, 0x59, 0x5c, 0x1d, 0x30, - 0xbc, 0xe9, 0x28, 0xe9, 0xf2, 0x7f, 0x78, 0xbf, 0x9e, 0x92, 0x8b, 0x7c, - 0x0a, 0xcf, 0xd8, 0xf4, 0xfe, 0x7c, 0xe9, 0xff, 0xae, 0x9e, 0xde, 0x87, - 0xd7, 0xd5, 0xce, 0x9d, 0x76, 0xb4, 0xe8, 0xfa, 0x6a, 0xaa, 0x7d, 0x14, - 0xdb, 0x95, 0xe9, 0x12, 0x7f, 0xed, 0x27, 0xf3, 0xbe, 0x96, 0xbd, 0x94, - 0x74, 0xf8, 0x59, 0xf7, 0xc3, 0xa1, 0x0f, 0xb1, 0xd2, 0x3c, 0xec, 0xf0, - 0xf3, 0xa7, 0xff, 0xbd, 0xd5, 0xed, 0x7b, 0x0f, 0x77, 0xe9, 0xe8, 0x9d, - 0x39, 0xb4, 0xc7, 0x49, 0x39, 0x3e, 0xf7, 0x4a, 0xb3, 0xfd, 0x96, 0xdc, - 0x6b, 0xfc, 0xb1, 0xd3, 0xff, 0x52, 0xb4, 0x9c, 0x5d, 0xb7, 0x9d, 0x73, - 0xa7, 0xfd, 0xb6, 0x4d, 0xa3, 0x0b, 0x9e, 0x9d, 0x3f, 0xaa, 0xed, 0xab, - 0xed, 0x0e, 0x92, 0xdd, 0xe5, 0x7d, 0x15, 0x1b, 0x63, 0x90, 0xb6, 0xd9, - 0x1e, 0x42, 0x33, 0xb2, 0xa1, 0x38, 0xba, 0x3f, 0x51, 0xec, 0xff, 0xe5, - 0xab, 0x1e, 0xba, 0xf8, 0x66, 0x01, 0xa2, 0x69, 0x9f, 0xfc, 0xb5, 0x63, - 0xd7, 0x5f, 0x0c, 0xc0, 0x34, 0x4e, 0x33, 0xff, 0x96, 0xac, 0x7a, 0xeb, - 0xe1, 0x98, 0x06, 0x8a, 0x06, 0x7d, 0xf0, 0xcc, 0x03, 0x45, 0xc1, 0x33, - 0x21, 0xd3, 0xf8, 0x5e, 0xc9, 0xcd, 0x28, 0xe9, 0x2e, 0x8f, 0xdb, 0x66, - 0x3e, 0x8a, 0x4f, 0xe4, 0x5f, 0x86, 0xee, 0xb8, 0x3a, 0x7f, 0x9e, 0xba, - 0xf8, 0x66, 0x01, 0xa2, 0x49, 0x92, 0xf6, 0x7e, 0xf8, 0x6b, 0x3e, 0xc5, - 0xf3, 0xc7, 0x67, 0x45, 0x8b, 0xe8, 0x8f, 0x9c, 0x3b, 0x08, 0x4e, 0xb8, - 0xa7, 0xda, 0x9d, 0xe1, 0x93, 0xa8, 0x56, 0x3a, 0x27, 0x9f, 0xf7, 0x9c, - 0x5d, 0x7c, 0x33, 0x00, 0xd1, 0x6a, 0x4f, 0xfb, 0x1e, 0xba, 0xf8, 0x66, - 0x01, 0xa2, 0x55, 0x83, 0xa4, 0xbf, 0x28, 0x9a, 0x52, 0x4b, 0xb2, 0x3c, - 0xfe, 0x5d, 0x7c, 0x33, 0x00, 0xd1, 0x14, 0xcf, 0xe5, 0xd7, 0xc3, 0x30, - 0x0d, 0x11, 0xa4, 0xde, 0xec, 0xe9, 0xe0, 0xcc, 0x03, 0x45, 0x3f, 0x36, - 0x98, 0xe8, 0xf9, 0xe0, 0x68, 0xae, 0x7f, 0xef, 0x75, 0xff, 0x5c, 0xb8, - 0x63, 0x97, 0x3a, 0x7f, 0xea, 0x73, 0xd1, 0xb2, 0xe1, 0x8e, 0x5c, 0xe9, - 0x2d, 0xde, 0x4c, 0x1e, 0x95, 0xc4, 0x8b, 0x49, 0x13, 0xff, 0x96, 0xac, - 0x7a, 0xeb, 0xe1, 0x98, 0x06, 0x89, 0xaa, 0x7f, 0x2e, 0xbe, 0x19, 0x80, - 0x68, 0xae, 0xe7, 0x83, 0x30, 0x0d, 0x15, 0xf4, 0xee, 0x38, 0xe0, 0xa9, - 0x09, 0x4b, 0x2f, 0xe3, 0xe7, 0xd0, 0xa4, 0xa9, 0xcf, 0x6b, 0x4e, 0x9c, - 0xe5, 0x6c, 0xe9, 0xff, 0x56, 0xf8, 0xcd, 0x5d, 0xaa, 0xc3, 0xa5, 0xa3, - 0xa7, 0xf9, 0x3f, 0x56, 0x23, 0xeb, 0x93, 0xa3, 0xe7, 0x91, 0x82, 0x12, - 0x5d, 0x26, 0x02, 0xe1, 0x16, 0x0e, 0x08, 0xe5, 0xe1, 0x0d, 0x3f, 0xf9, - 0x6a, 0xc7, 0xae, 0xbe, 0x19, 0x80, 0x68, 0x9e, 0xe7, 0xf2, 0xeb, 0xe1, - 0x98, 0x06, 0x8b, 0x86, 0x7f, 0xe5, 0xe3, 0xd7, 0x5f, 0x0c, 0xc0, 0x34, - 0x49, 0xf0, 0xcb, 0xa5, 0x36, 0x1d, 0xbc, 0xf3, 0xcc, 0x68, 0x60, 0x8e, - 0xe2, 0x9f, 0xe3, 0xa5, 0xda, 0xa5, 0xd4, 0xdd, 0x1e, 0x4f, 0xe5, 0xd7, - 0xc3, 0x30, 0x0d, 0x11, 0x54, 0xfe, 0x5d, 0x7c, 0x33, 0x00, 0xd1, 0x4c, - 0xcf, 0xfe, 0x5a, 0xb1, 0xeb, 0xaf, 0x86, 0x60, 0x1a, 0x26, 0x79, 0xff, - 0xcb, 0x56, 0x3d, 0x75, 0xf0, 0xcc, 0x03, 0x45, 0x1b, 0x16, 0x26, 0x3d, - 0xc9, 0xe7, 0x93, 0xcd, 0x29, 0xcf, 0xfc, 0xbc, 0x7a, 0xeb, 0xe1, 0x98, - 0x06, 0x88, 0xea, 0x6f, 0x76, 0x74, 0xfc, 0x94, 0x3c, 0xd5, 0x87, 0x4f, - 0xbe, 0x19, 0x80, 0x68, 0xa6, 0xa7, 0xff, 0x6d, 0x35, 0x7c, 0xb6, 0x9c, - 0x6d, 0xdc, 0xe9, 0xff, 0x9f, 0xb4, 0x1b, 0x2f, 0xeb, 0x7d, 0xc3, 0xa6, - 0x6f, 0x27, 0x4f, 0xc8, 0xca, 0xb2, 0xb8, 0x3a, 0x7f, 0xfa, 0xb5, 0xba, - 0x7f, 0xf0, 0x75, 0xbc, 0x79, 0xd3, 0x37, 0x67, 0x4f, 0xec, 0xb5, 0x81, - 0x01, 0x7f, 0x44, 0x80, 0x96, 0xf8, 0x4d, 0x8d, 0xa3, 0xfa, 0xf0, 0xa7, - 0x92, 0xdd, 0xe5, 0x45, 0x5c, 0x8b, 0xd1, 0x60, 0x18, 0xda, 0x95, 0xa8, - 0xd1, 0x27, 0xdf, 0x0c, 0xc0, 0x34, 0x55, 0x53, 0xfe, 0xc7, 0xae, 0xbe, - 0x19, 0x80, 0x68, 0x9b, 0x64, 0xba, 0x3f, 0x85, 0x18, 0xcf, 0xe5, 0xd7, - 0xc3, 0x30, 0x0d, 0x15, 0xfc, 0xfe, 0x5d, 0x7c, 0x33, 0x00, 0xd1, 0x63, - 0x4f, 0xbe, 0x19, 0x80, 0x68, 0xb5, 0x67, 0xfd, 0x8f, 0x5d, 0x7c, 0x33, - 0x00, 0xd1, 0x41, 0x49, 0x74, 0x7f, 0x0a, 0x31, 0x9f, 0x7c, 0x33, 0x00, - 0xd1, 0x71, 0x4f, 0x63, 0xb2, 0x58, 0x74, 0xf3, 0xb3, 0xb2, 0x01, 0xd3, - 0xf9, 0x95, 0x8e, 0x9b, 0xee, 0xc7, 0x49, 0x74, 0x8b, 0x1d, 0x98, 0xe1, - 0x26, 0x89, 0xa7, 0xdf, 0x0c, 0xc0, 0x34, 0x5d, 0x33, 0xe6, 0x1c, 0xe5, - 0x8e, 0x92, 0xe8, 0xf5, 0x90, 0xc6, 0x7f, 0xfe, 0x52, 0xe9, 0xed, 0xfe, - 0xfa, 0x5f, 0x6c, 0xac, 0x13, 0xa7, 0xff, 0xed, 0x8f, 0xb9, 0xd7, 0xa7, - 0xee, 0xbc, 0xd7, 0x2e, 0x7a, 0x74, 0xc1, 0x47, 0x43, 0x1f, 0xbf, 0x96, - 0x39, 0xff, 0x3e, 0xbf, 0xfc, 0x7d, 0x95, 0xc1, 0xd3, 0x87, 0x17, 0xf3, - 0xe2, 0xd1, 0x1c, 0xff, 0xbe, 0xd6, 0xef, 0x2f, 0xa6, 0xe0, 0xe9, 0xbd, - 0xd9, 0xd3, 0xe1, 0xad, 0xe6, 0x8e, 0x9f, 0x9f, 0x94, 0xe9, 0xb9, 0x3a, - 0x1d, 0xf3, 0xd3, 0xeb, 0x51, 0x2c, 0xfd, 0xde, 0x38, 0xf4, 0xd1, 0xd3, - 0xff, 0xfc, 0xdc, 0xee, 0xad, 0xd0, 0xe6, 0xfb, 0xcb, 0xdf, 0x3e, 0x07, - 0x4f, 0xea, 0xaa, 0xf3, 0xe7, 0x1e, 0x74, 0x79, 0x44, 0xd6, 0x99, 0xa7, - 0xff, 0xfb, 0x6c, 0x3e, 0xdf, 0x69, 0x7d, 0x6e, 0xb9, 0x4b, 0xd0, 0x9d, - 0x3c, 0x19, 0x80, 0x68, 0x93, 0x27, 0xc1, 0xd6, 0x9d, 0x67, 0x5b, 0x77, - 0xce, 0x9f, 0xd5, 0x6e, 0xb5, 0x8f, 0xb9, 0xd0, 0xc7, 0xe3, 0xf3, 0xe8, - 0x7a, 0x64, 0x5f, 0x65, 0x54, 0x27, 0x27, 0xee, 0x7b, 0x77, 0xef, 0xdf, - 0x51, 0xd3, 0xff, 0xb6, 0x9a, 0xb4, 0x13, 0xf7, 0x71, 0xb0, 0xe9, 0xf5, - 0x69, 0x15, 0x87, 0x4f, 0xf3, 0x6f, 0x49, 0x62, 0x98, 0x0e, 0x9f, 0xff, - 0x60, 0x7d, 0xb6, 0x35, 0xaa, 0x5f, 0x1c, 0x70, 0x54, 0x3d, 0x16, 0x37, - 0x25, 0xd1, 0xbc, 0xfc, 0x01, 0xe8, 0x0b, 0x1d, 0x3f, 0xfb, 0xd1, 0xcd, - 0x37, 0xef, 0xb6, 0x1d, 0x1d, 0x3b, 0x8e, 0x38, 0x2a, 0x7e, 0xfe, 0x58, - 0xa4, 0xb9, 0x4b, 0x2f, 0xe7, 0xd4, 0xaf, 0xd7, 0x5c, 0xe9, 0xf2, 0x6a, - 0xca, 0xe0, 0xe9, 0xfe, 0x60, 0xd8, 0xfb, 0xa6, 0xb9, 0xd3, 0xff, 0xed, - 0x6e, 0x9f, 0xd0, 0x36, 0x9a, 0xb4, 0x13, 0xe7, 0x47, 0xd1, 0x6a, 0xa2, - 0x81, 0x37, 0x9f, 0xea, 0xce, 0xfa, 0x57, 0x38, 0xf3, 0xa7, 0xff, 0x65, - 0x9b, 0x46, 0x1a, 0x71, 0x3e, 0x87, 0x45, 0x22, 0xc3, 0x45, 0xfc, 0x1d, - 0x4f, 0x86, 0xb7, 0x9a, 0x3a, 0x7f, 0xcf, 0x61, 0xb3, 0xc7, 0xc7, 0xd7, - 0x9d, 0x1d, 0x73, 0xe6, 0x70, 0x96, 0x7b, 0x56, 0x57, 0x27, 0x4f, 0xf2, - 0x79, 0xf1, 0xfe, 0xd4, 0x97, 0x3a, 0x1c, 0x3e, 0x0e, 0xa2, 0x39, 0xdc, - 0x71, 0xc1, 0xd3, 0xff, 0xea, 0x56, 0x85, 0xbb, 0xae, 0x6f, 0x4a, 0x60, - 0x29, 0x65, 0xfc, 0x52, 0x65, 0xc9, 0x08, 0x7d, 0xa2, 0xc9, 0x0e, 0x9f, - 0xb6, 0xdd, 0x01, 0x2c, 0x3a, 0x7e, 0xfe, 0x7c, 0x59, 0xe7, 0x43, 0xbb, - 0x3e, 0x8e, 0x43, 0xfe, 0x5d, 0x33, 0xd6, 0xef, 0x32, 0x4c, 0xfa, 0xc6, - 0xa6, 0x2f, 0x7c, 0x32, 0x2a, 0x34, 0x7f, 0x26, 0xc0, 0x73, 0x6c, 0x3e, - 0x90, 0xc1, 0xc2, 0xac, 0x67, 0x13, 0xcb, 0xc7, 0x1f, 0xa8, 0xf1, 0x3c, - 0x42, 0x72, 0x7f, 0xf7, 0xeb, 0x8e, 0x77, 0x4e, 0x0d, 0x7d, 0xe7, 0x4e, - 0xfd, 0x75, 0xce, 0x95, 0x7c, 0xfa, 0x94, 0x97, 0x3f, 0xf5, 0x6c, 0x5a, - 0xcf, 0x1b, 0xde, 0x75, 0xce, 0x9f, 0xb0, 0x17, 0xc7, 0x1c, 0x1d, 0x25, + 0xf9, 0x1b, 0xc7, 0x54, 0x61, 0x3e, 0xa1, 0x52, 0xec, 0xc3, 0x3f, 0xf8, + 0xe6, 0xc7, 0x9e, 0xbe, 0x19, 0x80, 0xa8, 0xa2, 0xa7, 0xf1, 0xeb, 0xe1, + 0x98, 0x0a, 0x8b, 0xa2, 0x7f, 0xe3, 0xe3, 0xcf, 0x5f, 0x0c, 0xc0, 0x54, + 0x49, 0x73, 0xf8, 0xf5, 0xf0, 0xcc, 0x05, 0x45, 0xe5, 0x0c, 0xe9, 0x08, + 0xac, 0x27, 0x79, 0xe5, 0x1e, 0x02, 0x9b, 0x87, 0x86, 0x3c, 0xdc, 0x31, + 0x86, 0xbf, 0x0c, 0xbc, 0x79, 0xda, 0x53, 0xf0, 0xf1, 0xd2, 0x6c, 0xff, + 0xe3, 0x9b, 0x1e, 0x7a, 0xf8, 0x66, 0x02, 0xa2, 0x59, 0x9b, 0xcd, 0xad, + 0x3c, 0x19, 0x80, 0xa8, 0x8c, 0xe7, 0xe2, 0x63, 0x59, 0x5c, 0x2d, 0x30, + 0xbd, 0x69, 0x19, 0x69, 0xf1, 0x7f, 0x78, 0x7f, 0x9e, 0x91, 0x8b, 0x7d, + 0x0a, 0xcf, 0xd8, 0xf2, 0xfe, 0x7d, 0x69, 0xff, 0xae, 0x5e, 0x5e, 0x87, + 0xc7, 0xd5, 0xd6, 0x9d, 0x76, 0xb5, 0x68, 0xfa, 0x6a, 0xa6, 0x7d, 0x14, + 0xdb, 0x95, 0xe9, 0x12, 0x7f, 0xed, 0x17, 0xf3, 0xbe, 0x96, 0xbd, 0x8c, + 0xb4, 0xf8, 0x59, 0xf7, 0xc5, 0xa0, 0x8f, 0xb1, 0xd2, 0x3c, 0xec, 0xf4, + 0xf5, 0xa7, 0xff, 0xbc, 0xd5, 0xed, 0x7b, 0x0f, 0x77, 0xe9, 0xe0, 0xad, + 0x39, 0xb4, 0xcb, 0x48, 0xb9, 0x3e, 0xf7, 0x4a, 0xb3, 0xfd, 0x96, 0xdc, + 0x6b, 0xfc, 0xb2, 0xd3, 0xff, 0x51, 0xb4, 0x5c, 0x5d, 0xb7, 0x9d, 0x75, + 0xa7, 0xfd, 0xb6, 0x2d, 0x93, 0x0b, 0x9e, 0x2d, 0x3f, 0xaa, 0xed, 0xab, + 0xec, 0x96, 0x91, 0xdd, 0xe5, 0x7d, 0x15, 0x1b, 0x63, 0x90, 0xb6, 0xd9, + 0x1e, 0x42, 0x33, 0xb2, 0xa1, 0x38, 0xba, 0x3f, 0x51, 0xec, 0xff, 0xe3, + 0x9b, 0x1e, 0x7a, 0xf8, 0x66, 0x02, 0xa2, 0x69, 0x9f, 0xfc, 0x73, 0x63, + 0xcf, 0x5f, 0x0c, 0xc0, 0x54, 0x4e, 0x33, 0xff, 0x8e, 0x6c, 0x79, 0xeb, + 0xe1, 0x98, 0x0a, 0x8a, 0x06, 0x7d, 0xf0, 0xcc, 0x05, 0x45, 0xc1, 0x33, + 0x12, 0xd3, 0xf8, 0x5e, 0xc5, 0xcd, 0x19, 0x69, 0x1e, 0x8f, 0xdb, 0x66, + 0x3e, 0x0a, 0x4f, 0xe2, 0x3f, 0xa6, 0xee, 0xb8, 0x5a, 0x7f, 0x9e, 0x7a, + 0xf8, 0x66, 0x02, 0xa2, 0x49, 0x91, 0xf6, 0x7e, 0xf8, 0x6b, 0x3e, 0xc3, + 0xf3, 0xc7, 0x6b, 0x45, 0x8b, 0xe8, 0x8f, 0x9c, 0x3b, 0x08, 0x4e, 0xb8, + 0xa7, 0xda, 0x9d, 0xe1, 0x93, 0xa8, 0x56, 0x3a, 0x27, 0x9f, 0xf7, 0xbc, + 0x3d, 0x7c, 0x33, 0x01, 0x51, 0x6a, 0x4f, 0xfb, 0x1e, 0x7a, 0xf8, 0x66, + 0x02, 0xa2, 0x55, 0x85, 0xa4, 0x7f, 0x68, 0x9a, 0x32, 0x4b, 0xb2, 0x3c, + 0xfe, 0x3d, 0x7c, 0x33, 0x01, 0x51, 0x14, 0xcf, 0xe3, 0xd7, 0xc3, 0x30, + 0x15, 0x11, 0xa4, 0xde, 0x6d, 0x69, 0xe0, 0xcc, 0x05, 0x45, 0x3f, 0x36, + 0x99, 0x68, 0xf9, 0xe0, 0x68, 0xae, 0x7f, 0xef, 0x35, 0xff, 0x1c, 0xb8, + 0x63, 0x97, 0x5a, 0x7f, 0xea, 0x73, 0xc1, 0xb2, 0xe1, 0x8e, 0x5d, 0x69, + 0x1d, 0xde, 0x4c, 0x1e, 0x95, 0xc4, 0x8b, 0x49, 0x13, 0xff, 0x8e, 0x6c, + 0x79, 0xeb, 0xe1, 0x98, 0x0a, 0x89, 0xaa, 0x7f, 0x1e, 0xbe, 0x19, 0x80, + 0xa8, 0xae, 0xe7, 0x83, 0x30, 0x15, 0x15, 0xf4, 0xee, 0x38, 0xe1, 0x29, + 0x0a, 0x47, 0x2f, 0xe3, 0xe7, 0xd0, 0x64, 0xa9, 0xcf, 0x6b, 0x56, 0x9c, + 0xe5, 0x6d, 0x69, 0xff, 0x56, 0xf8, 0xcd, 0x5d, 0xaa, 0xc5, 0xa5, 0xa5, + 0xa7, 0xf8, 0xbf, 0x56, 0x13, 0xeb, 0x95, 0xa3, 0xe7, 0x91, 0x82, 0x12, + 0x3d, 0x26, 0x02, 0xe1, 0x16, 0x0e, 0x08, 0xe5, 0xe1, 0x0d, 0x3f, 0xf8, + 0xe6, 0xc7, 0x9e, 0xbe, 0x19, 0x80, 0xa8, 0x9e, 0xe7, 0xf1, 0xeb, 0xe1, + 0x98, 0x0a, 0x8b, 0x86, 0x7f, 0xe3, 0xe3, 0xcf, 0x5f, 0x0c, 0xc0, 0x54, + 0x49, 0xf0, 0xcb, 0xa5, 0x36, 0x1d, 0xbc, 0xf3, 0xdc, 0x68, 0x60, 0x8e, + 0xe2, 0x9f, 0xe3, 0xa5, 0xda, 0xa5, 0xd4, 0xdd, 0x1e, 0x4f, 0xe3, 0xd7, + 0xc3, 0x30, 0x15, 0x11, 0x54, 0xfe, 0x3d, 0x7c, 0x33, 0x01, 0x51, 0x4c, + 0xcf, 0xfe, 0x39, 0xb1, 0xe7, 0xaf, 0x86, 0x60, 0x2a, 0x26, 0x79, 0xff, + 0xc7, 0x36, 0x3c, 0xf5, 0xf0, 0xcc, 0x05, 0x45, 0x1b, 0x16, 0x26, 0x3d, + 0xc9, 0xe7, 0xb3, 0xcd, 0x29, 0xcf, 0xfc, 0x7c, 0x79, 0xeb, 0xe1, 0x98, + 0x0a, 0x88, 0xea, 0x6f, 0x36, 0xb4, 0xfc, 0x54, 0x3c, 0xd5, 0x8b, 0x4f, + 0xbe, 0x19, 0x80, 0xa8, 0xa6, 0xa7, 0xff, 0x6c, 0xb5, 0x7c, 0xb6, 0x9c, + 0x6d, 0xdd, 0x69, 0xff, 0x9f, 0xb2, 0x1b, 0x2f, 0xe3, 0x7d, 0xc5, 0xa6, + 0x6f, 0x6b, 0x4f, 0xc4, 0xc6, 0xb2, 0xb8, 0x5a, 0x7f, 0xfa, 0xb5, 0xba, + 0x7f, 0xf0, 0x75, 0xbc, 0x7a, 0xd3, 0x37, 0x6b, 0x4f, 0xec, 0xb5, 0x80, + 0x80, 0xff, 0x44, 0x80, 0x96, 0xfa, 0x4d, 0x8d, 0xa3, 0xfa, 0xf0, 0xa7, + 0x91, 0xdd, 0xe5, 0x45, 0x5c, 0x8b, 0xd1, 0x60, 0x18, 0xda, 0x95, 0xa8, + 0xd1, 0x27, 0xdf, 0x0c, 0xc0, 0x54, 0x55, 0x53, 0xfe, 0xc7, 0x9e, 0xbe, + 0x19, 0x80, 0xa8, 0x9b, 0x64, 0x7a, 0x3f, 0x83, 0x18, 0xcf, 0xe3, 0xd7, + 0xc3, 0x30, 0x15, 0x15, 0xfc, 0xfe, 0x3d, 0x7c, 0x33, 0x01, 0x51, 0x63, + 0x4f, 0xbe, 0x19, 0x80, 0xa8, 0xb5, 0x67, 0xfd, 0x8f, 0x3d, 0x7c, 0x33, + 0x01, 0x51, 0x41, 0x48, 0xf4, 0x7f, 0x06, 0x31, 0x9f, 0x7c, 0x33, 0x01, + 0x51, 0x71, 0x4f, 0x63, 0xb1, 0x58, 0xb4, 0xf3, 0xb3, 0xb1, 0x02, 0xd3, + 0xf9, 0x8d, 0x8e, 0x9b, 0xee, 0xcb, 0x48, 0xf4, 0x8b, 0x1d, 0x98, 0xe1, + 0x26, 0x89, 0xa7, 0xdf, 0x0c, 0xc0, 0x54, 0x5d, 0x33, 0xe6, 0x1c, 0xe5, + 0x96, 0x91, 0xe8, 0xf5, 0x88, 0xc6, 0x7f, 0xfe, 0x31, 0xe9, 0xed, 0xfe, + 0xfa, 0x5f, 0x6c, 0x6c, 0x15, 0xa7, 0xff, 0xed, 0x8f, 0x99, 0xd7, 0xa7, + 0xee, 0xbd, 0xd7, 0x2e, 0x78, 0xb4, 0xc1, 0x4b, 0x43, 0x1f, 0xbf, 0xb6, + 0x39, 0xff, 0x3e, 0xbf, 0xfc, 0x7d, 0x95, 0xc2, 0xd3, 0x87, 0x0f, 0xf3, + 0xe2, 0xd1, 0x1c, 0xff, 0xbe, 0xd6, 0xef, 0x2f, 0xa6, 0xe1, 0x69, 0xbc, + 0xda, 0xd3, 0xe1, 0xad, 0xe6, 0x96, 0x9f, 0x9f, 0x94, 0xe9, 0xb9, 0x5a, + 0x1d, 0xf3, 0xd3, 0xeb, 0x51, 0x2c, 0xfd, 0xde, 0x38, 0xf2, 0xd2, 0xd3, + 0xff, 0xfc, 0xdc, 0xee, 0xad, 0xd0, 0xe6, 0xfb, 0xcb, 0xdf, 0x3e, 0x0b, + 0x4f, 0xea, 0xaa, 0xf7, 0xef, 0x1e, 0xb4, 0x7b, 0x44, 0xd6, 0x99, 0xa7, + 0xff, 0xfb, 0x6c, 0x3e, 0x5f, 0x65, 0x7d, 0x6e, 0xb9, 0x2b, 0xd0, 0xad, + 0x3c, 0x19, 0x80, 0xa8, 0x93, 0x27, 0xc1, 0xd6, 0x9d, 0x67, 0x5b, 0x77, + 0xd6, 0x9f, 0xd5, 0x6e, 0xb5, 0x8f, 0xba, 0xd0, 0xc7, 0xe3, 0xf3, 0xe8, + 0x7a, 0x64, 0x5f, 0x65, 0x34, 0x27, 0x27, 0xee, 0x7b, 0x77, 0xef, 0xdf, + 0x52, 0xd3, 0xff, 0xb6, 0x5a, 0xb4, 0x0b, 0xf7, 0x71, 0xb1, 0x69, 0xf5, + 0x68, 0x8d, 0x8b, 0x4f, 0xf3, 0x6f, 0x45, 0x61, 0x98, 0x16, 0x9f, 0xff, + 0x60, 0x7d, 0xb6, 0x35, 0xaa, 0x3f, 0x1c, 0x70, 0x94, 0x3d, 0x16, 0x37, + 0x25, 0xd1, 0xbc, 0xfc, 0x01, 0xe0, 0x0b, 0x2d, 0x3f, 0xfb, 0xc1, 0xcd, + 0x37, 0xef, 0xb6, 0x1d, 0x2d, 0x3b, 0x8e, 0x38, 0x4a, 0x7e, 0xfe, 0x58, + 0x62, 0xba, 0x47, 0x2f, 0xe7, 0xd4, 0x6f, 0xd7, 0x5d, 0x69, 0xf1, 0x6a, + 0xca, 0xe1, 0x69, 0xfe, 0x60, 0xd8, 0xf9, 0xa6, 0xba, 0xd3, 0xff, 0xed, + 0x6e, 0x9f, 0xd0, 0x36, 0x5a, 0xb4, 0x0b, 0xeb, 0x47, 0xd1, 0x6a, 0x62, + 0x81, 0x37, 0x9f, 0xea, 0xce, 0xfa, 0x57, 0x38, 0xf5, 0xa7, 0xff, 0x65, + 0x9b, 0x26, 0x1a, 0x70, 0xbe, 0x4b, 0x45, 0x22, 0xc3, 0x45, 0xfc, 0x1d, + 0x4f, 0x86, 0xb7, 0x9a, 0x5a, 0x7f, 0xcf, 0x61, 0xb3, 0xd7, 0xc7, 0xc7, + 0xad, 0x1d, 0x73, 0xe6, 0x70, 0x96, 0x7b, 0x56, 0x57, 0x2b, 0x4f, 0xf1, + 0x7b, 0xf5, 0xfe, 0xcc, 0x57, 0x5a, 0x1c, 0x3e, 0x0e, 0xa2, 0x39, 0xdc, + 0x71, 0xc2, 0xd3, 0xff, 0xea, 0x36, 0x85, 0xbb, 0xae, 0x6f, 0x46, 0x60, + 0x48, 0xe5, 0xfc, 0x52, 0x65, 0xc5, 0x08, 0x7d, 0xa2, 0xc8, 0x96, 0x9f, + 0xb6, 0xdd, 0x00, 0xac, 0x5a, 0x7e, 0xfe, 0x7c, 0x59, 0xeb, 0x43, 0xbb, + 0x3e, 0x8e, 0x43, 0xfe, 0x5d, 0x33, 0xce, 0xef, 0x32, 0x4c, 0xfa, 0xc6, + 0xa6, 0x2f, 0x7c, 0x32, 0x2a, 0x34, 0x7f, 0x66, 0xc0, 0x73, 0x6c, 0x3e, + 0x88, 0xc1, 0xc2, 0xac, 0x67, 0x13, 0xcb, 0xc7, 0x1f, 0xa8, 0xf1, 0x3d, + 0x42, 0x72, 0x7f, 0xf7, 0xeb, 0x8e, 0x77, 0x4e, 0x0d, 0x7d, 0xeb, 0x4e, + 0xfd, 0x75, 0xd6, 0x95, 0x7c, 0xfa, 0x8c, 0x97, 0x3f, 0xf5, 0x6c, 0x5a, + 0xcf, 0x5b, 0xde, 0x75, 0xd6, 0x9f, 0xb0, 0x0f, 0xc7, 0x1c, 0x2d, 0x23, 0xd3, 0x33, 0xa4, 0x23, 0x35, 0xf9, 0x96, 0x52, 0x5c, 0x86, 0x37, 0x1b, 0x93, 0xba, 0x49, 0x87, 0xb6, 0x6d, 0xfc, 0xca, 0x77, 0xb6, 0x1c, 0x5f, - 0x27, 0x51, 0xe7, 0x70, 0xb4, 0xbc, 0x36, 0x35, 0x09, 0x7f, 0x69, 0xa1, - 0xf3, 0xf9, 0x75, 0xf0, 0xcc, 0x03, 0x44, 0x6b, 0x3e, 0xf8, 0x66, 0x01, - 0xa2, 0xa5, 0x9b, 0x00, 0xd1, 0x0d, 0x49, 0x74, 0x7a, 0x58, 0x63, 0x3f, - 0xf2, 0xf1, 0xeb, 0xaf, 0x86, 0x60, 0x1a, 0x23, 0xe9, 0xf7, 0xc3, 0x30, - 0x0d, 0x16, 0x3c, 0xff, 0x0e, 0x79, 0xda, 0x30, 0xd8, 0x74, 0x97, 0x47, - 0xd2, 0xe1, 0x8c, 0xee, 0xb4, 0x57, 0x93, 0xa7, 0xe7, 0x7c, 0x6b, 0x79, - 0xa3, 0xa7, 0xf8, 0x73, 0xbb, 0xe6, 0xb5, 0x87, 0x4f, 0x76, 0xa4, 0xf9, - 0xd3, 0xff, 0xfc, 0xdf, 0x1a, 0xe6, 0xb7, 0xb4, 0x0d, 0xa6, 0xaf, 0x96, - 0x9d, 0x08, 0x88, 0x6d, 0x91, 0x4e, 0xcc, 0x03, 0x45, 0xa1, 0x3f, 0xec, - 0xe1, 0xd8, 0x33, 0xf6, 0x57, 0x07, 0x40, 0x1f, 0x47, 0xc9, 0xa7, 0xff, - 0xff, 0x93, 0xfb, 0xc1, 0x46, 0xd2, 0x6d, 0xaf, 0xba, 0xbf, 0xe8, 0x2b, - 0x47, 0x47, 0xd1, 0x31, 0xb2, 0x19, 0xf9, 0xd7, 0x8d, 0x0b, 0x76, 0x74, - 0xf9, 0xb5, 0x5b, 0x63, 0xa7, 0xff, 0xab, 0x57, 0xa7, 0x36, 0xce, 0xab, - 0x7b, 0x63, 0xa2, 0xc3, 0xf5, 0x12, 0x58, 0x64, 0x64, 0x54, 0x29, 0xa7, - 0xfd, 0xdb, 0x06, 0xd1, 0xcc, 0xcb, 0x0e, 0x9f, 0xe4, 0xf4, 0x5f, 0xf6, - 0xae, 0x4e, 0x9f, 0xff, 0xed, 0xd3, 0xc3, 0x69, 0xb6, 0xaf, 0xbf, 0x42, - 0xca, 0xb9, 0xd2, 0xab, 0xa2, 0x6f, 0x47, 0x13, 0xed, 0x6f, 0x07, 0xc9, - 0xd3, 0xfc, 0x3e, 0xd9, 0xce, 0xe8, 0x58, 0xe9, 0x86, 0xa8, 0xf8, 0x40, - 0xa2, 0x7f, 0x56, 0xdc, 0x4d, 0xa2, 0x8e, 0x9f, 0xcf, 0xaf, 0xdc, 0x5a, - 0xc3, 0xa7, 0x56, 0xf0, 0xe9, 0xf3, 0x9c, 0xfb, 0xe8, 0x9d, 0x1c, 0x9e, - 0x2e, 0x0d, 0x4f, 0xf5, 0x57, 0x14, 0x01, 0x5c, 0x1d, 0x14, 0x98, 0x0d, - 0xa6, 0x58, 0xef, 0x72, 0x29, 0xea, 0xde, 0x68, 0xe9, 0xf9, 0x07, 0xd7, - 0xd5, 0xce, 0x9f, 0xff, 0xe4, 0x1f, 0x5f, 0x57, 0xe9, 0x5a, 0x6b, 0x7b, - 0xcd, 0xed, 0x0e, 0x8f, 0x28, 0x94, 0xd1, 0x64, 0x96, 0xef, 0x2f, 0x74, + 0x27, 0x31, 0xe7, 0x70, 0xb4, 0xbc, 0x36, 0x35, 0x09, 0x7f, 0x29, 0xa1, + 0xf3, 0xf8, 0xf5, 0xf0, 0xcc, 0x05, 0x44, 0x6b, 0x3e, 0xf8, 0x66, 0x02, + 0xa2, 0xa5, 0x9b, 0x01, 0x51, 0x0d, 0x48, 0xf4, 0x7a, 0x58, 0x63, 0x3f, + 0xf1, 0xf1, 0xe7, 0xaf, 0x86, 0x60, 0x2a, 0x23, 0xe9, 0xf7, 0xc3, 0x30, + 0x15, 0x16, 0x3c, 0xff, 0x0e, 0x7b, 0xd9, 0x30, 0xd8, 0xb4, 0x8f, 0x47, + 0xd2, 0xe1, 0x8c, 0xee, 0xb4, 0x37, 0xb5, 0xa7, 0xe7, 0x7c, 0x6b, 0x79, + 0xa5, 0xa7, 0xf8, 0x73, 0xbb, 0xe6, 0xb5, 0x8b, 0x4f, 0x76, 0x62, 0xfa, + 0xd3, 0xff, 0xfc, 0xdf, 0x1a, 0xe6, 0xb7, 0xb2, 0x0d, 0x96, 0xaf, 0x96, + 0xad, 0x04, 0x88, 0x6d, 0x91, 0x4e, 0xcc, 0x05, 0x45, 0xa1, 0x3f, 0xec, + 0xe1, 0xd8, 0x33, 0xf6, 0x57, 0x0b, 0x40, 0x1f, 0x47, 0xc9, 0xa7, 0xff, + 0xff, 0x8b, 0xfb, 0xc1, 0x26, 0xd1, 0x6d, 0xaf, 0xba, 0xbf, 0xe8, 0x2b, + 0x4b, 0x47, 0xd1, 0x31, 0xb2, 0x19, 0xf9, 0xd7, 0xad, 0x0b, 0x76, 0xb4, + 0xf9, 0xb5, 0x5b, 0x65, 0xa7, 0xff, 0xab, 0x57, 0xa7, 0x36, 0xce, 0xab, + 0x7b, 0x65, 0xa2, 0xc3, 0xf5, 0x12, 0x58, 0x64, 0x64, 0x54, 0x29, 0xa7, + 0xfd, 0xdb, 0x06, 0xc9, 0xcc, 0xcb, 0x16, 0x9f, 0xe2, 0xf0, 0x5f, 0xf6, + 0xae, 0x56, 0x9f, 0xff, 0xed, 0xd3, 0xc3, 0x65, 0xb6, 0xaf, 0xbf, 0x42, + 0xc6, 0xba, 0xd2, 0xab, 0xa2, 0x6f, 0x47, 0x13, 0xed, 0x6f, 0x07, 0xda, + 0xd3, 0xfc, 0x3e, 0x59, 0xce, 0xe8, 0x59, 0x69, 0x86, 0xa8, 0xf8, 0x40, + 0xa2, 0x7f, 0x56, 0xdc, 0x2d, 0x91, 0x96, 0x9f, 0xcf, 0xaf, 0xdc, 0x5a, + 0xc5, 0xa7, 0x56, 0xf1, 0x69, 0xf3, 0x9c, 0xf9, 0xe0, 0xad, 0x1c, 0x9e, + 0x2e, 0x0d, 0x4f, 0xf5, 0x57, 0x14, 0x01, 0x5c, 0x2d, 0x14, 0x98, 0x0d, + 0xa6, 0x58, 0xef, 0x72, 0x29, 0xea, 0xde, 0x69, 0x69, 0xf8, 0x87, 0xc7, + 0xd5, 0xd6, 0x9f, 0xff, 0xe2, 0x1f, 0x1f, 0x57, 0xe9, 0x5a, 0x6b, 0x7b, + 0xcd, 0xec, 0x96, 0x8f, 0x68, 0x94, 0xd1, 0x64, 0x8e, 0xef, 0x2f, 0x74, 0x75, 0x84, 0xac, 0x61, 0xcc, 0x2f, 0x6a, 0x32, 0x2d, 0xc3, 0xaf, 0xb2, - 0x61, 0x86, 0xcd, 0xe1, 0x13, 0xa8, 0xca, 0xfa, 0x8f, 0x7c, 0x42, 0xd2, - 0x7e, 0x76, 0x4e, 0x45, 0x9c, 0x3a, 0x7a, 0xb7, 0x9a, 0x3a, 0x4e, 0xfd, - 0x1e, 0x80, 0x98, 0x4f, 0xbe, 0x19, 0x80, 0x68, 0xb5, 0xa7, 0xfd, 0x8f, - 0x5d, 0x7c, 0x33, 0x00, 0xd1, 0x41, 0xc9, 0x7d, 0x62, 0x28, 0xe8, 0xad, - 0x46, 0x33, 0xff, 0x96, 0xac, 0x7a, 0xeb, 0xe1, 0x98, 0x06, 0x8a, 0x2e, - 0x7f, 0x2e, 0xbe, 0x19, 0x80, 0x68, 0xba, 0xa1, 0xec, 0xb1, 0x70, 0x84, - 0x72, 0x13, 0x2a, 0x16, 0xdb, 0x9f, 0x10, 0xee, 0x3d, 0x4b, 0x9d, 0x69, - 0x4e, 0x7d, 0xf0, 0xcc, 0x03, 0x44, 0x43, 0x3b, 0x75, 0xc9, 0xd2, 0x5d, - 0x1e, 0x6d, 0xa6, 0x33, 0xf9, 0x75, 0xf0, 0xcc, 0x03, 0x44, 0x6d, 0x3f, - 0x97, 0x5f, 0x0c, 0xc0, 0x34, 0x53, 0x73, 0xf9, 0x75, 0xf0, 0xcc, 0x03, - 0x45, 0x41, 0x3f, 0x97, 0x5f, 0x0c, 0xc0, 0x34, 0x54, 0xd3, 0xef, 0x86, - 0x60, 0x1a, 0x2b, 0x09, 0xf2, 0x71, 0xcf, 0xbf, 0x3a, 0x7f, 0x9e, 0xba, - 0xf8, 0x66, 0x01, 0xa2, 0x3f, 0x9d, 0x4d, 0x61, 0xd2, 0x5d, 0x22, 0xe0, - 0x0c, 0x70, 0xa8, 0x50, 0xa7, 0xff, 0x2d, 0x58, 0xf5, 0xd7, 0xc3, 0x30, - 0x0d, 0x13, 0x7c, 0xff, 0xca, 0xc7, 0xae, 0xbe, 0x19, 0x80, 0x68, 0x9f, - 0xa7, 0xdd, 0x6d, 0xdf, 0xea, 0xab, 0x4e, 0x96, 0xce, 0x87, 0x74, 0x78, - 0xde, 0x9b, 0x4f, 0xf7, 0x5a, 0xdb, 0xcd, 0x6b, 0x33, 0x83, 0xa7, 0xdd, - 0x3c, 0xff, 0x00, 0xe9, 0xf7, 0x58, 0xee, 0xfb, 0xf2, 0xc7, 0x4f, 0xff, - 0x33, 0x33, 0x33, 0x33, 0x33, 0x5b, 0x73, 0xa7, 0xdf, 0x4b, 0x31, 0x45, - 0x4d, 0xc7, 0x05, 0x45, 0x1b, 0xfe, 0x09, 0xe5, 0xe9, 0x4b, 0x34, 0x30, - 0xc8, 0xca, 0xbc, 0x2a, 0x67, 0xff, 0xea, 0x55, 0xf5, 0xfc, 0xb3, 0x9d, - 0xb5, 0xf5, 0xee, 0xce, 0x9f, 0x60, 0x6d, 0x3e, 0x74, 0xff, 0xff, 0xe1, - 0xcf, 0x29, 0xf6, 0x7f, 0x4d, 0xa2, 0xb9, 0x6e, 0x9d, 0x5e, 0xed, 0x3e, - 0x74, 0xf6, 0x3d, 0x2d, 0x3a, 0x39, 0x4c, 0x93, 0xeb, 0xdb, 0x25, 0x18, - 0x40, 0x4f, 0xff, 0x9d, 0x9a, 0xd7, 0xe0, 0xf7, 0xd3, 0xb4, 0xfa, 0x79, - 0x3a, 0x7a, 0xc5, 0x23, 0xce, 0x9f, 0x5c, 0x7d, 0xc7, 0x9d, 0x3f, 0xb6, - 0xca, 0x5f, 0x7d, 0xb1, 0xd2, 0xfb, 0x1f, 0xed, 0x11, 0x21, 0x3c, 0xff, - 0x9a, 0xde, 0x7c, 0x37, 0x5f, 0x7e, 0xdc, 0xe9, 0x75, 0xce, 0x9a, 0xf4, - 0x74, 0x21, 0xa9, 0xec, 0x52, 0x7f, 0xee, 0x5b, 0x59, 0x7a, 0xde, 0xd1, - 0x47, 0x4e, 0xd2, 0x38, 0x74, 0x31, 0xef, 0xdd, 0x0e, 0x19, 0x5d, 0x5a, - 0x46, 0x96, 0xe2, 0x1f, 0xe1, 0xb4, 0xa3, 0x21, 0x70, 0xd4, 0x20, 0x27, - 0x39, 0xe1, 0x47, 0x4f, 0xf5, 0x6a, 0xf5, 0xad, 0xd7, 0x67, 0x46, 0x1e, - 0xb8, 0x8f, 0xcd, 0x82, 0x74, 0x7c, 0xda, 0x28, 0x82, 0x77, 0x1c, 0x70, - 0x74, 0xf5, 0x82, 0x8c, 0x52, 0xcb, 0xf9, 0xad, 0x79, 0xd3, 0xfb, 0xcb, - 0x6a, 0xfb, 0xcf, 0x4e, 0x99, 0x00, 0xe9, 0x5a, 0xc7, 0xc1, 0xe4, 0x5f, - 0x46, 0xb0, 0xc9, 0x83, 0x6d, 0x03, 0xd8, 0x47, 0xcf, 0xfd, 0x67, 0xbd, - 0xd0, 0xfa, 0xe3, 0x6b, 0x0e, 0x9f, 0xf9, 0xb7, 0xe3, 0x9d, 0x25, 0x38, - 0xca, 0x3a, 0x79, 0xb5, 0x70, 0x34, 0x41, 0xd3, 0xf6, 0x6d, 0xba, 0xfe, - 0xbc, 0xe8, 0xfa, 0x3a, 0xd4, 0x8f, 0xa4, 0x67, 0x45, 0xb3, 0x7f, 0x93, - 0xa6, 0xe3, 0x83, 0xa1, 0xe6, 0xbf, 0x81, 0x79, 0xeb, 0xb2, 0x3a, 0x29, - 0x66, 0x8a, 0x7d, 0x7f, 0x1c, 0xf7, 0x73, 0xa1, 0x0f, 0x7b, 0xc1, 0x94, - 0xee, 0x38, 0xe0, 0xa8, 0x29, 0x65, 0xfc, 0xf2, 0x70, 0x8e, 0x15, 0x00, - 0x6e, 0xd0, 0x66, 0x11, 0x38, 0xad, 0xc3, 0xb8, 0x5f, 0x67, 0x0a, 0x5c, - 0xe9, 0xee, 0x70, 0x7b, 0x3a, 0x7f, 0xe6, 0x1e, 0xc5, 0xad, 0x71, 0x87, - 0xb3, 0xa1, 0x11, 0x01, 0xd8, 0xd5, 0xc8, 0xa7, 0xcd, 0x5f, 0xda, 0x1d, - 0x3d, 0xcd, 0x2b, 0xae, 0x74, 0x38, 0x79, 0x6e, 0x89, 0x67, 0xed, 0x53, - 0x82, 0xca, 0x3c, 0x40, 0x53, 0xec, 0x1e, 0x76, 0xc6, 0x88, 0x09, 0x66, - 0xe6, 0x7e, 0xfb, 0x3f, 0x2d, 0xe0, 0xe9, 0xfe, 0x6f, 0xd9, 0xd2, 0x9c, - 0x45, 0x1d, 0x3c, 0xa6, 0xa5, 0x1d, 0x3e, 0x6e, 0xd2, 0xdb, 0x9d, 0x3f, - 0xbe, 0xe5, 0xd0, 0x74, 0x87, 0x4f, 0x5b, 0xdf, 0xd8, 0xa9, 0xb8, 0xe0, - 0xa8, 0x63, 0x77, 0xc1, 0x1c, 0xfd, 0x9f, 0x7b, 0xc5, 0x0a, 0x59, 0xa1, - 0x86, 0x55, 0x2d, 0x4f, 0x68, 0xbd, 0xf4, 0x3d, 0x97, 0x61, 0xd8, 0x90, - 0x68, 0xa3, 0xd8, 0x47, 0x4f, 0xbd, 0xd7, 0xb9, 0xe0, 0xd1, 0x03, 0xcf, - 0xfb, 0x7e, 0xd8, 0xdd, 0x1b, 0x4d, 0xc9, 0xd3, 0xb3, 0xf6, 0x1d, 0x37, - 0x1c, 0x1d, 0x3f, 0xbe, 0x94, 0xeb, 0xc3, 0xd6, 0x06, 0xd3, 0x81, 0xc8, - 0xe5, 0x18, 0x7f, 0x76, 0x9f, 0xf8, 0x6b, 0xce, 0xf1, 0xfe, 0x32, 0xd6, - 0x3a, 0x18, 0xfa, 0xa8, 0x92, 0x7f, 0xf5, 0x29, 0x58, 0xfa, 0xf8, 0x66, - 0x01, 0xa2, 0x18, 0x8d, 0x9f, 0x90, 0x90, 0x4f, 0xbe, 0x19, 0x80, 0x68, - 0x82, 0xa7, 0x6d, 0x94, 0x74, 0x51, 0xe6, 0x21, 0x8c, 0xf6, 0xae, 0xdd, - 0x95, 0x3b, 0x3f, 0x61, 0x53, 0xde, 0x8e, 0x79, 0x2a, 0x7f, 0x25, 0x95, - 0xab, 0xb7, 0x65, 0x41, 0x53, 0xf5, 0x03, 0x6d, 0x94, 0x54, 0xdc, 0x70, - 0x54, 0xfc, 0x2c, 0x36, 0x27, 0xca, 0x8a, 0x4c, 0x2c, 0x08, 0x94, 0x39, - 0xb2, 0x3e, 0xcc, 0xc4, 0x2b, 0x82, 0xaf, 0x03, 0x13, 0x27, 0xca, 0x59, - 0xf9, 0xcb, 0x1e, 0x9e, 0x26, 0xe3, 0x9e, 0x9f, 0xf3, 0x3f, 0x06, 0xaf, - 0xf6, 0xb9, 0xd3, 0xfd, 0xad, 0xb3, 0xae, 0x5b, 0xb6, 0x3a, 0x7f, 0x9a, - 0xd7, 0xf5, 0x30, 0x52, 0x8e, 0x86, 0x3f, 0x5d, 0x9d, 0xcf, 0xff, 0xce, - 0x66, 0x3f, 0x37, 0xd2, 0xac, 0xf7, 0x5e, 0xe7, 0x83, 0x45, 0xf7, 0x3e, - 0x4d, 0x0d, 0x3c, 0xe9, 0xff, 0x0a, 0x3f, 0x5b, 0xaf, 0xa5, 0xce, 0x9f, - 0xda, 0xef, 0xc0, 0xbf, 0x74, 0x78, 0x80, 0x67, 0x67, 0xde, 0x78, 0x80, - 0x62, 0x8f, 0xab, 0xd4, 0x29, 0xb1, 0xe7, 0x88, 0x06, 0x7b, 0x06, 0xd7, - 0x9e, 0x20, 0x19, 0xfc, 0x81, 0xba, 0xef, 0xb6, 0x3c, 0x40, 0x33, 0x90, - 0x79, 0x3c, 0x40, 0x31, 0xca, 0x2d, 0xd4, 0x45, 0xb2, 0xe7, 0x47, 0xf3, - 0xbe, 0xda, 0x3c, 0x40, 0x30, 0x78, 0x80, 0x66, 0x65, 0x1e, 0x20, 0x18, - 0xe4, 0xdc, 0xa0, 0xbc, 0xf2, 0x2b, 0x96, 0x3c, 0x40, 0x33, 0xb5, 0x80, - 0x78, 0x80, 0x67, 0xfc, 0x38, 0xf5, 0xed, 0x03, 0x3e, 0x78, 0x80, 0x66, - 0xce, 0x4f, 0x10, 0x0c, 0xfe, 0x1c, 0xe2, 0xf7, 0x6e, 0xcf, 0x10, 0x0c, - 0xf9, 0x3c, 0xe0, 0xf6, 0x78, 0x80, 0x66, 0x4b, 0x9e, 0x20, 0x18, 0xf9, - 0xeb, 0xe8, 0xd6, 0x7d, 0xa1, 0x6b, 0x5e, 0x68, 0x80, 0x66, 0xed, 0x8f, - 0x10, 0x0a, 0xcd, 0xa4, 0xf9, 0x19, 0x59, 0xc9, 0xe2, 0x01, 0x9e, 0xf7, - 0x04, 0x0f, 0x10, 0x0c, 0xe6, 0xf8, 0x1e, 0x20, 0x19, 0xff, 0x55, 0xb7, - 0xe5, 0xa8, 0x7b, 0xb9, 0xe2, 0x01, 0x9f, 0x7b, 0x8f, 0x7b, 0x1e, 0x20, - 0x18, 0xa4, 0x40, 0x6d, 0x32, 0x6f, 0xf6, 0x78, 0x80, 0x61, 0xea, 0xa4, - 0x39, 0x23, 0xa8, 0x4b, 0xa2, 0xb6, 0xcc, 0xfb, 0x33, 0xb9, 0x6e, 0xa1, - 0x4f, 0xe9, 0x14, 0xfa, 0xb5, 0x7c, 0xb4, 0xf1, 0x00, 0xcf, 0xee, 0x58, - 0x1c, 0xfb, 0x68, 0xf1, 0x00, 0xf2, 0x6d, 0x27, 0x7d, 0xb8, 0x3c, 0x40, - 0x30, 0x07, 0xf5, 0xf5, 0x19, 0xe4, 0x17, 0xdc, 0xf1, 0x00, 0xcf, 0xd8, - 0xe3, 0xea, 0xd7, 0x9e, 0x20, 0x18, 0xa4, 0x44, 0xf6, 0x43, 0xe9, 0x6c, - 0xff, 0x6d, 0xae, 0xbb, 0xfb, 0xfe, 0xcf, 0x10, 0x0c, 0x90, 0xf1, 0x00, - 0xcd, 0x96, 0x72, 0x7c, 0x9b, 0x48, 0x9b, 0xfd, 0x9e, 0x20, 0x19, 0xf6, - 0x6a, 0xe9, 0x69, 0xe2, 0x01, 0x9f, 0x90, 0x7d, 0x7d, 0x5c, 0xf1, 0x00, - 0xc3, 0x22, 0x44, 0x49, 0x34, 0x69, 0x1c, 0xb2, 0x03, 0x6a, 0x1b, 0x2e, - 0x20, 0x7d, 0x87, 0x64, 0x38, 0x5d, 0xd9, 0x3d, 0xe5, 0x6c, 0x6a, 0x3c, - 0x2e, 0xa8, 0x4a, 0xf8, 0x86, 0x04, 0xec, 0xc0, 0x34, 0x40, 0x2b, 0x45, - 0xf4, 0xf7, 0x97, 0x77, 0xca, 0x8e, 0x9f, 0xf9, 0xe3, 0x41, 0xb4, 0xef, - 0xbf, 0x5c, 0x3a, 0x6e, 0xd8, 0xa9, 0x79, 0x2a, 0x76, 0xda, 0xc3, 0xa6, - 0xe3, 0x82, 0xa1, 0x0f, 0x73, 0xae, 0x2c, 0xe0, 0x97, 0x03, 0x93, 0x94, - 0x97, 0x29, 0x67, 0x83, 0x16, 0x32, 0xc2, 0x1e, 0x4a, 0x14, 0x97, 0x14, - 0x38, 0xc2, 0xbe, 0xe1, 0xc7, 0x3f, 0x93, 0x5e, 0x1d, 0x3a, 0x6b, 0x9d, - 0x3f, 0x7d, 0xc7, 0xb7, 0xec, 0x3a, 0x7f, 0xcf, 0xbf, 0x41, 0xa5, 0x37, - 0xfc, 0x9d, 0x3f, 0xf7, 0xf7, 0x94, 0xf6, 0xff, 0x7e, 0x14, 0x74, 0xfd, - 0xe3, 0x8f, 0xa5, 0x6c, 0xa9, 0xe7, 0x37, 0x8e, 0x1d, 0x3e, 0xa7, 0x1e, - 0xd6, 0x9d, 0x3d, 0x42, 0xcf, 0x2a, 0x3e, 0x7d, 0x42, 0x46, 0xec, 0x51, - 0x0c, 0x9c, 0x05, 0x17, 0xa2, 0x0e, 0xd1, 0xb2, 0x13, 0x33, 0xc8, 0x3a, - 0xb9, 0xd3, 0xbd, 0x77, 0x2e, 0x74, 0xff, 0xdd, 0xaa, 0x83, 0x69, 0xce, - 0xfd, 0xf2, 0x74, 0xfe, 0xe5, 0xad, 0xbd, 0x5b, 0xa3, 0xa7, 0xf9, 0xb4, - 0x80, 0x9c, 0xb6, 0x8e, 0x9b, 0x57, 0xa3, 0xeb, 0xf9, 0xac, 0xfe, 0x7d, - 0x5f, 0xc5, 0xf5, 0x47, 0x43, 0x26, 0x6c, 0x84, 0x59, 0x0b, 0x3f, 0x4b, - 0x67, 0xd8, 0xeb, 0x9e, 0x58, 0xe9, 0xaf, 0x73, 0xa7, 0x71, 0xc7, 0x07, - 0x4d, 0xde, 0x14, 0xb2, 0xfe, 0x3e, 0x7b, 0x57, 0x35, 0x9f, 0xf5, 0x5c, - 0x73, 0xcb, 0x82, 0x8e, 0x1d, 0x3b, 0x3b, 0xa2, 0xa1, 0xe9, 0x80, 0x2a, - 0x10, 0x9b, 0x22, 0xea, 0x3f, 0x9f, 0xda, 0x1a, 0xb7, 0xbf, 0x0f, 0x3a, - 0x7f, 0x86, 0x9d, 0x52, 0xf8, 0xe3, 0x82, 0xa7, 0x2b, 0x34, 0x74, 0x6c, - 0xf5, 0xdd, 0x1e, 0x4f, 0xa9, 0xc7, 0xb3, 0xce, 0x86, 0x4c, 0x79, 0x11, - 0xb2, 0x11, 0xba, 0x24, 0x9f, 0x9d, 0xc4, 0xfb, 0x7c, 0x4e, 0x9f, 0xfd, - 0x5c, 0xe2, 0xaa, 0xd7, 0xd7, 0x75, 0xc9, 0xd3, 0x6f, 0x0e, 0x99, 0xcb, - 0x9d, 0x3e, 0xa7, 0x48, 0x3c, 0xd1, 0xac, 0xf0, 0x2b, 0x1d, 0x11, 0x6e, - 0xb7, 0x79, 0xee, 0x6b, 0x78, 0x74, 0xff, 0xcd, 0x42, 0xfd, 0xd0, 0x8b, - 0x70, 0x74, 0x93, 0xe8, 0x86, 0x12, 0x5d, 0x10, 0xc5, 0x8d, 0xc4, 0x03, - 0xe3, 0xd7, 0xe6, 0x51, 0x8f, 0x92, 0xf0, 0x85, 0x82, 0x10, 0xfe, 0x96, - 0xec, 0xa6, 0x8d, 0xc7, 0x71, 0xda, 0x60, 0xc6, 0xad, 0xa9, 0x4b, 0xfe, - 0xa0, 0x3a, 0x8d, 0xb6, 0x7f, 0xab, 0xe2, 0xda, 0x7d, 0x6c, 0xe9, 0xf8, - 0x7b, 0xae, 0x71, 0xe7, 0x4f, 0xb1, 0xfd, 0x39, 0x43, 0xa7, 0xde, 0x1c, - 0x7b, 0x75, 0xca, 0x86, 0x45, 0xd5, 0x1b, 0x6c, 0xb7, 0xc1, 0x4c, 0xff, - 0xde, 0x47, 0xdc, 0xf1, 0x57, 0x46, 0x13, 0xa7, 0x75, 0x27, 0x27, 0x47, - 0xcf, 0x91, 0x48, 0xb2, 0xf0, 0x68, 0x81, 0x65, 0xa3, 0x50, 0x29, 0x24, - 0xd1, 0xbc, 0xe0, 0x7e, 0x7f, 0xc9, 0xd5, 0xb4, 0xf0, 0xbe, 0xfb, 0x62, - 0xa7, 0xff, 0xf6, 0xdb, 0xfd, 0xd3, 0xa4, 0xbd, 0xe8, 0x43, 0x07, 0xb3, - 0xa7, 0xfe, 0xbe, 0x5b, 0xd1, 0x4d, 0x43, 0xae, 0xa3, 0xa3, 0x68, 0xa8, - 0xd3, 0x04, 0x32, 0x61, 0xe9, 0x0e, 0xc9, 0xff, 0xfe, 0xfd, 0x94, 0x8e, - 0x66, 0x3e, 0xec, 0xae, 0x76, 0xc2, 0x07, 0x4e, 0xb0, 0x5e, 0x74, 0x32, - 0xa3, 0xc5, 0x2f, 0x6e, 0x33, 0x6c, 0x27, 0xf5, 0x96, 0x7f, 0x3d, 0xca, - 0x1c, 0xdd, 0x1d, 0x3f, 0xfb, 0xe0, 0x34, 0xe8, 0x69, 0xbe, 0xd7, 0x3a, - 0x7f, 0x63, 0x9b, 0xa5, 0x55, 0xce, 0x8a, 0x3f, 0x97, 0x48, 0xf3, 0xf2, - 0x79, 0xd5, 0x52, 0x8e, 0x9f, 0x57, 0x29, 0xfb, 0x9d, 0x3f, 0xfd, 0x7d, - 0x5a, 0x09, 0xbe, 0x8e, 0xd5, 0xb4, 0x51, 0xd2, 0x6b, 0x0f, 0xef, 0x82, - 0x78, 0x44, 0x7a, 0x6c, 0x8f, 0x50, 0xa8, 0x9f, 0xf0, 0xa7, 0x8b, 0x69, - 0xd5, 0xad, 0xe0, 0xe9, 0xdc, 0xe7, 0xce, 0x9f, 0x77, 0x83, 0x4e, 0xc7, - 0x43, 0x1e, 0x2f, 0xa3, 0x93, 0x95, 0x6b, 0x87, 0x4f, 0xfc, 0xab, 0xa9, - 0xb9, 0x6f, 0xfa, 0xdd, 0x9d, 0x0c, 0x7c, 0x88, 0x3d, 0x0c, 0xac, 0x05, - 0xf1, 0xcf, 0x51, 0xa5, 0xe1, 0x13, 0xa8, 0x43, 0x4f, 0xfe, 0x7a, 0x6e, - 0x9c, 0x47, 0x3d, 0x76, 0xf6, 0xe7, 0x4f, 0x9a, 0xc6, 0x76, 0x63, 0xa7, - 0xef, 0x7c, 0x6e, 0xad, 0xb9, 0xd3, 0xff, 0xff, 0xef, 0xb6, 0x87, 0x01, - 0x2e, 0xe2, 0x7c, 0x1a, 0xfa, 0x6b, 0x5b, 0xc5, 0x5c, 0xe9, 0xff, 0xff, - 0xff, 0x5e, 0xf5, 0xad, 0xe2, 0xaf, 0xff, 0xa5, 0xba, 0xcc, 0xf3, 0x54, - 0xe7, 0xba, 0x6e, 0x2d, 0x63, 0xa1, 0x93, 0x1f, 0xc8, 0x40, 0xcf, 0x77, - 0x96, 0xdc, 0xe9, 0xb8, 0xe0, 0xe8, 0xb9, 0xbb, 0xe0, 0x8e, 0x7c, 0x9b, - 0xca, 0xd9, 0x4b, 0x34, 0x51, 0x6a, 0xa8, 0x2d, 0xa8, 0x3b, 0x85, 0x23, - 0x1a, 0x85, 0xe1, 0x09, 0x3b, 0x8e, 0x38, 0x2a, 0x79, 0xfa, 0xa0, 0x29, - 0x65, 0xfc, 0xfa, 0xb9, 0x4e, 0xee, 0x7b, 0xbf, 0xa5, 0x9f, 0x3e, 0x41, - 0x2f, 0x9b, 0xf7, 0x3a, 0x73, 0xa6, 0x03, 0xa1, 0x8d, 0x92, 0x0b, 0x4f, - 0xc3, 0x6d, 0xdc, 0xad, 0x1d, 0x3f, 0xfc, 0x3a, 0x72, 0xbf, 0x58, 0xa6, - 0xda, 0x72, 0x74, 0xfa, 0xce, 0xba, 0x55, 0xa7, 0x4f, 0x92, 0xed, 0x62, - 0x8f, 0x67, 0xec, 0xf9, 0xb3, 0xfd, 0xfa, 0x7b, 0x3f, 0x66, 0xc7, 0x9e, - 0xcf, 0xd9, 0xef, 0x5f, 0x57, 0x3d, 0x9f, 0xb1, 0xc9, 0xe8, 0x89, 0x14, - 0xf9, 0xaa, 0xf4, 0x27, 0xb3, 0xf6, 0x0f, 0x67, 0xec, 0xd9, 0xa3, 0xd9, - 0xfa, 0xa2, 0xde, 0x4f, 0x13, 0xf9, 0xf5, 0x22, 0x7a, 0xba, 0x93, 0xb3, - 0xd9, 0xfb, 0x07, 0xb3, 0xf6, 0x6e, 0xd8, 0xf6, 0x7e, 0xcf, 0xf5, 0x77, - 0x9f, 0xa7, 0x55, 0xc9, 0xec, 0xfd, 0x9f, 0xab, 0x69, 0x7f, 0x6c, 0x3d, - 0x9f, 0xb1, 0xda, 0x29, 0x44, 0x8e, 0xe8, 0xf3, 0xdf, 0xb1, 0xb4, 0x7b, - 0x3f, 0x60, 0xf6, 0x7e, 0xd1, 0xaf, 0x9b, 0x8e, 0x0f, 0x67, 0xec, 0x3d, - 0x58, 0xa7, 0x26, 0x95, 0x08, 0x6b, 0x61, 0x37, 0xf2, 0x85, 0x18, 0xde, - 0x17, 0x9a, 0x5f, 0xe0, 0x9a, 0x7a, 0x9e, 0xde, 0x4b, 0x67, 0xe9, 0x68, - 0x91, 0x9f, 0xf5, 0x07, 0x35, 0xfe, 0x33, 0x6e, 0x1d, 0x33, 0xec, 0x2a, - 0x2c, 0x44, 0xc5, 0xa8, 0x42, 0x7f, 0x1f, 0x5c, 0x9a, 0xc9, 0xc6, 0x99, - 0xff, 0xf3, 0xfe, 0xce, 0xb1, 0xc6, 0xe7, 0x6c, 0xac, 0x70, 0xe9, 0xfc, - 0xed, 0x97, 0x4b, 0xb9, 0x47, 0x45, 0xa8, 0x8d, 0xfa, 0xc4, 0x32, 0xf3, - 0x5b, 0xd6, 0x28, 0x7d, 0x0b, 0xb2, 0x73, 0xa3, 0xd8, 0x5d, 0x4f, 0xfb, - 0xcb, 0x5a, 0x2d, 0xbd, 0xfa, 0x07, 0x4f, 0xc3, 0x9e, 0x77, 0x8f, 0x3a, - 0x77, 0x1c, 0x70, 0x54, 0xef, 0x0d, 0xd9, 0x4b, 0x2f, 0xe7, 0xfc, 0x38, - 0xff, 0x1f, 0xa7, 0x59, 0xf3, 0xa7, 0xf8, 0x73, 0xbe, 0x8f, 0x6e, 0xed, - 0x3a, 0x39, 0x4c, 0xd5, 0x48, 0x1d, 0xa6, 0x09, 0x6e, 0x90, 0x27, 0xfc, - 0x22, 0x9e, 0xbb, 0x97, 0xea, 0x6d, 0x1d, 0x3b, 0x8e, 0x38, 0x2c, 0x42, - 0x09, 0xf7, 0xc3, 0x30, 0x0b, 0x10, 0x81, 0x66, 0xb6, 0x77, 0x1c, 0x70, - 0x58, 0x83, 0xd0, 0x58, 0x83, 0xcb, 0x35, 0xb3, 0x32, 0xa9, 0x12, 0xe0, - 0xdf, 0x3e, 0xd3, 0x69, 0x94, 0x74, 0xf0, 0xa3, 0x79, 0x3a, 0x77, 0x86, - 0xec, 0xe8, 0xb0, 0xdf, 0xa8, 0x86, 0x7c, 0x0d, 0xb6, 0x51, 0x53, 0xe1, - 0xc1, 0x1a, 0x2a, 0x6a, 0x02, 0xa6, 0xe3, 0x82, 0xa2, 0x8f, 0xd2, 0xe4, - 0xba, 0x23, 0xe0, 0x52, 0x7f, 0x0f, 0x86, 0xef, 0x74, 0xec, 0x52, 0xcd, - 0xe4, 0x32, 0x6f, 0xc8, 0xcb, 0x90, 0xd2, 0x9f, 0xf9, 0xbb, 0xbd, 0x57, - 0x38, 0x39, 0xe4, 0xe9, 0xff, 0xf5, 0xaf, 0xbf, 0x0d, 0xfd, 0xb2, 0x6d, - 0x85, 0x0e, 0x8d, 0xa2, 0x63, 0x11, 0x27, 0xf5, 0xfc, 0x2a, 0xfc, 0x65, - 0xa7, 0x43, 0x2e, 0x11, 0xd2, 0x62, 0x46, 0x13, 0xf8, 0xea, 0xb2, 0x19, - 0x77, 0x22, 0x9d, 0xc7, 0x1c, 0x15, 0x3d, 0xde, 0x0f, 0x25, 0x2c, 0xbf, - 0x9f, 0xbc, 0x57, 0xea, 0x9c, 0x3a, 0x1e, 0x7b, 0xf7, 0x31, 0x9f, 0xfe, - 0x1b, 0x7a, 0x5b, 0xdb, 0x08, 0x65, 0x83, 0x87, 0x4f, 0xff, 0xff, 0xf6, - 0xaf, 0xe2, 0xfd, 0x37, 0x89, 0xa4, 0xd8, 0x27, 0x47, 0xa6, 0xf0, 0x74, - 0xfa, 0xfd, 0x1d, 0x3f, 0xfd, 0x4c, 0xbe, 0x45, 0xbd, 0x0a, 0xf2, 0x9f, - 0x3a, 0x79, 0xdb, 0x7d, 0xba, 0x3a, 0x1e, 0x7e, 0xf8, 0x9f, 0x3f, 0xf9, - 0xf5, 0xfe, 0xd4, 0x97, 0xf1, 0x76, 0xa3, 0xa7, 0x93, 0x9a, 0x51, 0xd0, - 0xca, 0x83, 0x5e, 0x45, 0x4a, 0x39, 0x18, 0x68, 0x90, 0xfa, 0x97, 0x3f, - 0x75, 0xee, 0x83, 0x6b, 0xce, 0x9f, 0xf6, 0x7f, 0xa9, 0x37, 0x59, 0x6f, - 0x67, 0x4f, 0xfa, 0xf7, 0x6f, 0xe9, 0x97, 0xca, 0x1d, 0x3f, 0xe1, 0xc7, - 0x37, 0x9f, 0xfa, 0x72, 0x74, 0x52, 0x3b, 0x80, 0xc5, 0x10, 0x54, 0x7d, - 0x3c, 0xff, 0x14, 0xe1, 0xd3, 0xef, 0xf3, 0x54, 0x27, 0x4f, 0xfd, 0xd7, - 0x4a, 0xdb, 0x3a, 0xbe, 0xda, 0xd3, 0xa3, 0x0f, 0xbe, 0xe4, 0xd3, 0xfd, - 0x43, 0xfa, 0xbd, 0x26, 0xce, 0x9f, 0xfe, 0xad, 0x5e, 0x9c, 0xdb, 0x3a, - 0xad, 0xed, 0x8e, 0x9e, 0xad, 0x25, 0xce, 0x9f, 0x9d, 0xd3, 0x82, 0xef, - 0x59, 0xe9, 0xd1, 0x73, 0xdb, 0xd1, 0x04, 0x72, 0x99, 0x18, 0x10, 0x89, - 0xae, 0xa1, 0x57, 0x3f, 0xfc, 0x97, 0xae, 0x75, 0x74, 0xf3, 0xbc, 0x14, - 0x3a, 0x7f, 0xff, 0x0e, 0xab, 0x68, 0xda, 0x4e, 0xd9, 0xeb, 0xe3, 0x8e, - 0x0a, 0x9e, 0xe6, 0xab, 0xc9, 0x53, 0xd9, 0xde, 0x68, 0xe9, 0xcf, 0x1f, - 0x4d, 0x10, 0xcc, 0xee, 0x38, 0xe0, 0xa9, 0xd4, 0x20, 0x52, 0xcb, 0xf9, - 0xff, 0x55, 0x95, 0xce, 0x3c, 0x5a, 0xc3, 0xa3, 0xb3, 0xe6, 0x12, 0x89, - 0xfc, 0xf1, 0xad, 0x6b, 0xdb, 0x0e, 0x86, 0x4e, 0xaa, 0xc6, 0x2e, 0x48, - 0xed, 0x21, 0xfc, 0x2b, 0xb0, 0x8a, 0x79, 0x34, 0x8c, 0x74, 0xfe, 0xf6, - 0xbf, 0xdf, 0x68, 0x27, 0x4f, 0xff, 0x3d, 0x39, 0xdf, 0x8b, 0xd7, 0xc3, - 0x30, 0x0d, 0x10, 0x64, 0xff, 0xef, 0xe3, 0xaa, 0x10, 0xda, 0x77, 0xe3, - 0x47, 0x43, 0x22, 0xa3, 0xd5, 0xc8, 0xda, 0x3f, 0xf5, 0x0d, 0xc9, 0xb7, - 0xe9, 0xd3, 0xdf, 0x4e, 0x3a, 0xe7, 0x42, 0x1b, 0xdb, 0x8b, 0xcf, 0xee, - 0xaa, 0xbf, 0x55, 0x7d, 0x8e, 0x87, 0xa7, 0xb4, 0x91, 0x8f, 0x5d, 0x97, - 0x44, 0x13, 0xff, 0xcc, 0x36, 0x74, 0x71, 0x06, 0xb9, 0xa1, 0xf2, 0x74, - 0xe6, 0xfb, 0x87, 0x43, 0x2f, 0x8a, 0x72, 0x75, 0x51, 0xdb, 0x02, 0x12, - 0x47, 0xf3, 0x92, 0x8e, 0x3d, 0x43, 0xea, 0x52, 0x9f, 0x62, 0xb2, 0xae, - 0x74, 0xff, 0xf0, 0x35, 0xee, 0xca, 0xad, 0x25, 0xf7, 0x87, 0x4f, 0xe1, - 0x16, 0x7a, 0x99, 0x0e, 0x9f, 0xda, 0x47, 0x49, 0xa7, 0xb1, 0x52, 0x51, - 0xd3, 0xf5, 0x0f, 0x9f, 0xb2, 0xd0, 0xf0, 0xfc, 0x19, 0xc5, 0x26, 0x08, - 0x89, 0x97, 0x72, 0x9e, 0xff, 0xb6, 0xbc, 0xe9, 0xfc, 0x2f, 0x1a, 0x53, - 0x01, 0xd3, 0x95, 0xcd, 0x1d, 0x0c, 0x7d, 0xf4, 0x49, 0x85, 0xf3, 0xb4, - 0x96, 0x1d, 0x3f, 0xef, 0x75, 0x7f, 0x1f, 0xed, 0x49, 0x73, 0xa7, 0xf5, - 0xda, 0xca, 0x14, 0xf2, 0x74, 0xff, 0xcc, 0x39, 0xb6, 0xed, 0x7f, 0xbd, - 0xca, 0x8e, 0x51, 0x73, 0x48, 0x6a, 0x33, 0x9f, 0x6d, 0x12, 0xdb, 0x9d, - 0x3f, 0xfe, 0xae, 0x7a, 0x62, 0x55, 0xda, 0xca, 0x14, 0xf2, 0x74, 0x15, - 0x3f, 0x5f, 0xc3, 0x7d, 0x94, 0x54, 0x15, 0x05, 0x41, 0x50, 0x54, 0x3c, - 0xf8, 0x10, 0x2b, 0xb2, 0xef, 0x42, 0xba, 0x82, 0x9d, 0x82, 0xa6, 0xdd, - 0x15, 0x3f, 0x66, 0x69, 0xc6, 0x51, 0x5d, 0x0b, 0x59, 0x3b, 0x85, 0x41, - 0x50, 0x54, 0x3c, 0xb4, 0x40, 0xa8, 0x2a, 0x0a, 0x82, 0xa0, 0xa8, 0x2a, - 0x0a, 0x8b, 0x0d, 0xe7, 0x21, 0x48, 0x15, 0xd8, 0x55, 0xc2, 0x9d, 0x05, - 0x41, 0x50, 0x54, 0x3c, 0xb4, 0xb8, 0x54, 0x15, 0x05, 0x41, 0x50, 0x54, - 0x3c, 0xd4, 0x76, 0x15, 0xa0, 0xa7, 0x60, 0xa8, 0x2a, 0x0a, 0x82, 0xa0, - 0xa8, 0xb0, 0xd4, 0x79, 0x0a, 0xf8, 0x56, 0xc2, 0xa5, 0xe4, 0xa8, 0x2a, - 0x0a, 0x82, 0xa0, 0xa8, 0xe4, 0xd4, 0x5a, 0x15, 0xd8, 0x57, 0xa1, 0x50, - 0x54, 0x15, 0x05, 0x4f, 0xb6, 0xdd, 0xde, 0x8a, 0x82, 0xa1, 0xe7, 0x9e, - 0x01, 0x5b, 0x0a, 0xc0, 0xae, 0xc9, 0xe4, 0x05, 0x41, 0x50, 0x54, 0x15, - 0x05, 0x43, 0xcd, 0x45, 0xa1, 0x48, 0x14, 0xe8, 0x2a, 0x0a, 0x82, 0xa0, - 0xa8, 0x2a, 0x1e, 0x6a, 0x39, 0x0a, 0xd8, 0x50, 0x85, 0x4b, 0x65, 0x41, - 0x50, 0x54, 0x9e, 0x54, 0x15, 0x69, 0x61, 0x05, 0x41, 0x50, 0x54, 0x15, - 0x16, 0x1f, 0x33, 0xc2, 0xbc, 0x8d, 0x00, 0xd3, 0x81, 0x5d, 0x85, 0x68, - 0x2a, 0x54, 0x54, 0x15, 0x05, 0x49, 0xe5, 0x41, 0x56, 0x96, 0x10, 0x54, - 0x15, 0x0c, 0x7a, 0x4f, 0x0a, 0x41, 0xaf, 0x8d, 0x28, 0x2a, 0x0a, 0x82, - 0xa0, 0xa8, 0x2a, 0x0a, 0x86, 0x36, 0x56, 0x85, 0x7c, 0x29, 0x41, 0x42, - 0x15, 0x05, 0x41, 0x50, 0x54, 0x7c, 0xbe, 0xb8, 0x56, 0x82, 0xa0, 0xa8, - 0x2a, 0x0a, 0x85, 0x17, 0xc2, 0x15, 0xa0, 0xa9, 0x28, 0xa8, 0x2a, 0x0a, - 0x8e, 0xcb, 0x4f, 0x42, 0xa0, 0xa8, 0x2a, 0x0a, 0x82, 0xa1, 0x8d, 0x43, - 0x81, 0x5b, 0x0a, 0xf4, 0x2a, 0x19, 0x7e, 0xc6, 0xc7, 0x27, 0x9e, 0xf2, - 0x53, 0x4b, 0x60, 0xdb, 0x6a, 0x42, 0x33, 0xf5, 0xcf, 0x9c, 0x3a, 0xfc, - 0x23, 0x94, 0x91, 0xb3, 0x7c, 0x65, 0xec, 0xec, 0x5d, 0xae, 0xcf, 0xa6, - 0x1f, 0x5e, 0x5d, 0x32, 0xf0, 0x97, 0xd4, 0x59, 0xe0, 0x91, 0xd9, 0x2a, - 0x7c, 0xf1, 0x6a, 0xb9, 0x4b, 0x4d, 0x62, 0x72, 0x32, 0x8a, 0x9e, 0x40, - 0xcf, 0x9d, 0x39, 0x39, 0xa3, 0xa7, 0x37, 0x85, 0xda, 0x88, 0xcf, 0x9c, - 0x6c, 0x6b, 0x43, 0xf3, 0xfb, 0x69, 0xc7, 0x3f, 0x6b, 0x0e, 0x8b, 0x51, - 0x0c, 0xe2, 0x8c, 0xdd, 0xb1, 0xd3, 0xf7, 0xf0, 0x7c, 0x37, 0x67, 0x4d, - 0x9f, 0x3a, 0x48, 0x70, 0x16, 0xb2, 0x03, 0xa4, 0xa3, 0xa6, 0xea, 0x5a, - 0x22, 0x57, 0xe2, 0xdb, 0x43, 0xc1, 0xdf, 0x01, 0xf3, 0xfd, 0xb6, 0x55, - 0x38, 0xc3, 0x61, 0xd1, 0x48, 0x91, 0xed, 0x66, 0x7e, 0x52, 0x75, 0x60, - 0xf6, 0x74, 0xff, 0xf3, 0x74, 0xcf, 0xff, 0x3b, 0x65, 0xf1, 0xc7, 0x07, - 0x43, 0x22, 0x0f, 0xd2, 0xf8, 0xb1, 0xb0, 0x04, 0x7c, 0x65, 0x3c, 0xc2, - 0x78, 0x0b, 0x12, 0x1a, 0xae, 0x18, 0x28, 0x9f, 0x29, 0x5a, 0x23, 0x1a, - 0x5e, 0xa1, 0x4d, 0x3f, 0x98, 0x75, 0x83, 0xed, 0x1d, 0x3f, 0x3c, 0x51, - 0xfb, 0xa3, 0xa7, 0xd6, 0x27, 0xd9, 0xe7, 0x47, 0xcf, 0x48, 0x4a, 0xe7, - 0xfd, 0xb6, 0xff, 0x63, 0x5c, 0x67, 0x67, 0x4e, 0xaa, 0x70, 0xe9, 0x56, - 0xcf, 0x6b, 0xb3, 0xf9, 0xfb, 0xdf, 0xfa, 0xac, 0x13, 0xa7, 0x94, 0xd5, - 0x61, 0xd3, 0xea, 0x74, 0x2d, 0x69, 0xd0, 0x87, 0x93, 0x72, 0x19, 0xe6, - 0x1d, 0x01, 0xd2, 0x6a, 0x4d, 0x68, 0x5e, 0xee, 0x51, 0xa7, 0x7e, 0xa2, - 0x19, 0xef, 0x73, 0xef, 0x3a, 0x79, 0xbd, 0x77, 0x2e, 0x54, 0xf9, 0xeb, - 0xe3, 0x8e, 0x0e, 0x81, 0x3d, 0x2f, 0x49, 0xe3, 0x94, 0x4b, 0x53, 0xa4, - 0x29, 0x57, 0x37, 0x71, 0xee, 0x7b, 0x0e, 0x79, 0xfb, 0xfe, 0xf7, 0x42, - 0x07, 0x4f, 0xf5, 0x83, 0x4f, 0xdd, 0x77, 0x73, 0xa7, 0xb9, 0xe5, 0x9d, - 0x1d, 0x3f, 0xfd, 0xb6, 0x50, 0x36, 0xab, 0xe1, 0x98, 0x06, 0x8b, 0xe2, - 0x76, 0x7e, 0xc3, 0x45, 0xff, 0x0c, 0x88, 0x00, 0x57, 0x9f, 0xdc, 0x66, - 0xae, 0xd5, 0x61, 0xd3, 0xff, 0x3a, 0xd7, 0x96, 0x17, 0xd6, 0xd1, 0x47, - 0x4f, 0xd5, 0xc7, 0x8d, 0xe6, 0x8e, 0x9f, 0xff, 0x6b, 0xc3, 0xd9, 0xd2, - 0x0f, 0x7f, 0x46, 0x55, 0x15, 0x3d, 0xbf, 0x16, 0xe8, 0xe8, 0xb1, 0x15, - 0x74, 0x5e, 0x0a, 0xf3, 0x6a, 0x8e, 0x9f, 0x7d, 0x2c, 0xc5, 0x1a, 0x61, - 0x39, 0xed, 0x7a, 0xd8, 0x69, 0x84, 0xe6, 0xed, 0x8d, 0x40, 0x9c, 0xfe, - 0x1c, 0xf3, 0xa6, 0xff, 0x66, 0xa0, 0x4e, 0x7f, 0x5e, 0xb6, 0x97, 0xf6, - 0xc3, 0x4c, 0x27, 0x35, 0x72, 0x69, 0x84, 0xe6, 0xe3, 0x83, 0xcc, 0x27, - 0x14, 0x9a, 0x7d, 0xa6, 0x88, 0x5c, 0xa2, 0x3b, 0xa0, 0xba, 0x41, 0xe0, - 0x8e, 0x5a, 0x2c, 0xc2, 0x65, 0x9f, 0x3c, 0x92, 0xd4, 0xfe, 0xb8, 0x8f, - 0x2e, 0x31, 0x5a, 0x5d, 0xe1, 0xe3, 0xa9, 0x45, 0x33, 0x87, 0xb5, 0x1d, - 0x3f, 0xcd, 0xee, 0x85, 0x1d, 0x78, 0x51, 0xd3, 0x86, 0xaf, 0x47, 0xb1, - 0xf1, 0xc8, 0x65, 0xd4, 0x3e, 0x4e, 0x42, 0x14, 0xbb, 0x21, 0xd4, 0xb7, - 0xe7, 0x50, 0x95, 0x9f, 0x73, 0x5f, 0x4f, 0x27, 0x4f, 0x86, 0xbc, 0x53, - 0x87, 0x4f, 0xf6, 0xf1, 0x5b, 0x46, 0xb5, 0xe7, 0x4f, 0xde, 0x05, 0xfd, - 0x59, 0x61, 0xd0, 0x87, 0xd5, 0xd9, 0xc4, 0x0a, 0x2d, 0x35, 0x09, 0x29, - 0xff, 0x56, 0x6d, 0xc4, 0x1d, 0xd5, 0xa7, 0x43, 0x2f, 0x8e, 0xd4, 0xeb, - 0x82, 0x36, 0x64, 0x37, 0x44, 0x9e, 0x7f, 0xf2, 0xb5, 0x74, 0x1b, 0x5f, - 0xa4, 0xba, 0x1d, 0x3f, 0xff, 0x86, 0xad, 0xab, 0xe0, 0xed, 0x1b, 0x5b, - 0xf7, 0x14, 0x74, 0xfc, 0x3e, 0xa9, 0x36, 0xc7, 0x4f, 0xff, 0xb0, 0x75, - 0x99, 0xb1, 0x6d, 0x5f, 0x8a, 0xd9, 0xd3, 0xfe, 0xb3, 0x06, 0xfa, 0xda, - 0x35, 0xce, 0x9d, 0xfb, 0xdc, 0xf1, 0x01, 0xcf, 0xfe, 0xfb, 0x6d, 0xba, - 0x57, 0xc3, 0x30, 0x0d, 0x10, 0x1a, 0xcd, 0x4c, 0x62, 0x32, 0xbc, 0x33, - 0x47, 0x69, 0xa0, 0x6a, 0x31, 0xc8, 0xa4, 0xe5, 0xd2, 0x36, 0xc9, 0xe1, - 0xd7, 0x7e, 0x9d, 0x3f, 0xff, 0x3e, 0xae, 0x9f, 0xfa, 0x2b, 0xc6, 0xb7, - 0x5c, 0x68, 0xe8, 0xa4, 0x40, 0x61, 0x1c, 0xff, 0xff, 0x63, 0xe8, 0x5c, - 0x7d, 0x5a, 0xff, 0x0d, 0xda, 0xf8, 0xe3, 0x82, 0xa3, 0x68, 0x8e, 0x12, - 0x19, 0xfc, 0xd5, 0xf0, 0xcc, 0x03, 0x44, 0x13, 0x3f, 0xcd, 0xaa, 0xf8, - 0x66, 0x01, 0xa2, 0xf9, 0x9f, 0x23, 0xa1, 0xab, 0xf2, 0x7f, 0x80, 0x77, - 0x3f, 0xbd, 0xdf, 0x56, 0xd0, 0x36, 0x74, 0xff, 0xac, 0xcb, 0x7a, 0xab, - 0x43, 0x8e, 0x8e, 0x9d, 0xc7, 0x1c, 0x15, 0x3e, 0xdd, 0x06, 0x7c, 0xa5, - 0x97, 0xf3, 0xff, 0xf9, 0xcf, 0xb3, 0xae, 0x9e, 0x73, 0xa7, 0x87, 0x2f, - 0xd2, 0xad, 0xd1, 0xd1, 0xa4, 0x52, 0x78, 0x34, 0x8b, 0x13, 0x2b, 0x18, - 0xc1, 0xa7, 0xfe, 0xb1, 0x4d, 0x6d, 0xc6, 0xac, 0xf0, 0xf3, 0xa7, 0xff, - 0xbc, 0x5a, 0x3d, 0x03, 0x69, 0xdf, 0x6d, 0xf7, 0x9d, 0x3f, 0xef, 0x6e, - 0xd4, 0x3a, 0x77, 0xf8, 0x03, 0xa7, 0x71, 0xc7, 0x05, 0x4f, 0xef, 0x1d, - 0xb0, 0xd5, 0xba, 0x29, 0x65, 0xfc, 0xff, 0xfc, 0xee, 0x74, 0x0d, 0xa7, - 0x3c, 0xd7, 0x1d, 0x35, 0x7a, 0xb0, 0xe9, 0x66, 0xd1, 0x57, 0xea, 0x24, - 0x3d, 0x5c, 0xef, 0x27, 0xe9, 0x1b, 0x0f, 0xca, 0x94, 0x90, 0x2a, 0xba, - 0x8c, 0x36, 0x7d, 0xba, 0xd3, 0x8f, 0x3a, 0x7f, 0xd5, 0xa6, 0xfd, 0xf6, - 0xc3, 0xa3, 0xc4, 0x11, 0x3f, 0x9a, 0xbe, 0x19, 0x80, 0x68, 0x82, 0x16, - 0x79, 0x33, 0xf6, 0x6f, 0xff, 0x4e, 0x0e, 0x9f, 0xba, 0xfc, 0xf1, 0x82, - 0xf3, 0xa0, 0x4f, 0x7f, 0xd2, 0xd8, 0xda, 0x67, 0xdd, 0xb8, 0x8c, 0x2a, - 0xe7, 0xf9, 0x87, 0x5e, 0x2b, 0x79, 0x69, 0xd3, 0xff, 0xd9, 0xc6, 0xab, - 0x6c, 0x9a, 0x1a, 0xda, 0x1d, 0x0f, 0x44, 0x28, 0x9c, 0xcf, 0xf6, 0xdb, - 0xfa, 0x16, 0xab, 0x4e, 0x9f, 0xff, 0xe4, 0xb1, 0x9f, 0x7f, 0xfd, 0x2d, - 0x71, 0xf9, 0xf5, 0x55, 0xa7, 0x4f, 0x6b, 0x74, 0x3c, 0xa2, 0x83, 0x66, - 0xf3, 0xf7, 0x85, 0x5f, 0x8c, 0xb4, 0xe8, 0x63, 0xeb, 0xd1, 0xd4, 0xf2, - 0x38, 0x9c, 0x1d, 0x3f, 0xfe, 0xf6, 0xc1, 0x6a, 0xda, 0xdb, 0x55, 0xbf, - 0x7e, 0x74, 0xfa, 0xb5, 0x7f, 0x17, 0xe4, 0xfe, 0x3c, 0x11, 0x4f, 0xc1, - 0xb4, 0xea, 0x4f, 0x27, 0x4f, 0xca, 0x6e, 0xbe, 0xea, 0xc3, 0xa7, 0xff, - 0xff, 0x93, 0x58, 0xac, 0x1e, 0xde, 0x97, 0xf5, 0x5b, 0x46, 0xd6, 0xfd, - 0xc5, 0x1d, 0x1c, 0xa3, 0x79, 0x0c, 0x30, 0xc6, 0x7e, 0x1e, 0xe9, 0x4d, - 0xb3, 0xa7, 0x7f, 0xc5, 0xce, 0x9f, 0xf6, 0x08, 0x57, 0xc3, 0x30, 0x0d, - 0x10, 0x8c, 0x31, 0xf1, 0xfa, 0x3d, 0x3f, 0xf9, 0xaa, 0xdf, 0x1a, 0x41, - 0xf5, 0xf5, 0x73, 0xa7, 0xff, 0xb3, 0x2c, 0xf1, 0x5b, 0xc5, 0x2f, 0x8e, - 0x38, 0x3a, 0x39, 0x44, 0xfb, 0x89, 0x73, 0xfd, 0xcb, 0x5e, 0xed, 0x65, - 0x70, 0x74, 0x51, 0xef, 0xe1, 0x2c, 0xee, 0x38, 0xe0, 0xa9, 0xfe, 0xae, - 0xf3, 0xf4, 0xea, 0xb9, 0x29, 0x65, 0xfc, 0xdc, 0x70, 0x54, 0xee, 0x38, - 0xe0, 0xa9, 0xfb, 0x2c, 0xe7, 0x6d, 0x72, 0x96, 0x5f, 0xc0, 0xa2, 0xf7, - 0x84, 0x9e, 0xa3, 0x79, 0xf0, 0x27, 0x3e, 0x14, 0x52, 0xcd, 0x9c, 0xee, - 0x38, 0xe0, 0xa9, 0xd7, 0x6f, 0x94, 0xb2, 0xfe, 0x5d, 0xa2, 0x20, 0xb4, - 0xb1, 0x3f, 0x72, 0x2c, 0xfc, 0x03, 0xa7, 0xf7, 0x8f, 0xf2, 0x8e, 0x9b, - 0x93, 0xa7, 0xfe, 0xde, 0x3c, 0x73, 0xcb, 0x82, 0x8e, 0x1d, 0x3f, 0x6e, - 0x9d, 0x56, 0xae, 0x74, 0x01, 0xf9, 0xe9, 0x16, 0x3e, 0x8f, 0x7d, 0x95, - 0x8c, 0x2a, 0xe1, 0x93, 0x54, 0xa8, 0xc8, 0x27, 0x5b, 0xd6, 0xbb, 0xba, - 0x3a, 0x7f, 0xf5, 0x75, 0xf0, 0x7b, 0xa0, 0x6d, 0xb2, 0x8e, 0x9f, 0x81, - 0x2f, 0xb4, 0x70, 0xa9, 0xfc, 0x35, 0x6b, 0xee, 0x9e, 0x4e, 0x9e, 0xcc, - 0xff, 0x93, 0xa3, 0xa1, 0xeb, 0x58, 0x69, 0x3c, 0xd8, 0xa7, 0x45, 0x4e, - 0xe3, 0x8e, 0x0a, 0x9f, 0xfe, 0xf0, 0xdd, 0xd5, 0x0e, 0xb6, 0x8c, 0x36, - 0x14, 0xb2, 0xfe, 0x54, 0x08, 0x9f, 0x52, 0x0c, 0x32, 0x7c, 0x6f, 0x2c, - 0xb5, 0x29, 0x21, 0x05, 0xb8, 0x62, 0x4f, 0xff, 0x95, 0x40, 0xc3, 0x9a, - 0xbf, 0x3e, 0xe7, 0xde, 0x74, 0xf9, 0xb5, 0x77, 0x54, 0x74, 0x31, 0xfe, - 0x69, 0x52, 0x7f, 0xf9, 0x1d, 0x50, 0xf2, 0x39, 0xc5, 0x0e, 0x79, 0x3a, - 0x7f, 0xff, 0xb9, 0xda, 0x71, 0x4e, 0xc8, 0xac, 0xd5, 0xfd, 0x7d, 0x5b, - 0xa3, 0xa2, 0x91, 0x79, 0x8a, 0x10, 0xcd, 0xad, 0xed, 0x89, 0x2f, 0x8f, - 0xd7, 0x98, 0xcd, 0xaa, 0x70, 0xed, 0x23, 0xaf, 0x72, 0x17, 0x7f, 0x8c, - 0xb5, 0x50, 0x99, 0xdc, 0x64, 0x58, 0x5f, 0xdc, 0x23, 0xc6, 0x32, 0x0b, - 0xcb, 0x05, 0xd4, 0xa0, 0xbf, 0x61, 0xa1, 0xc4, 0x37, 0x67, 0x3a, 0x61, - 0x3a, 0x7f, 0xfa, 0x85, 0x7a, 0xf2, 0x96, 0xdf, 0x75, 0xde, 0x1d, 0x2b, - 0x5e, 0x7d, 0xbc, 0x8e, 0x4f, 0xdb, 0x71, 0x36, 0x8a, 0x3a, 0x7f, 0xc2, - 0xda, 0xde, 0x77, 0x96, 0xdc, 0xe9, 0xce, 0x7b, 0xf3, 0xa7, 0xfd, 0x89, - 0xfa, 0xb5, 0x7c, 0x71, 0xc1, 0xd1, 0x87, 0xbf, 0x71, 0xe9, 0xff, 0xe1, - 0x67, 0xf4, 0xf1, 0xa4, 0x1f, 0x5f, 0x57, 0x3a, 0x29, 0x33, 0xd0, 0x2d, - 0xdc, 0x27, 0x7b, 0x21, 0x9f, 0xcc, 0x2f, 0x1a, 0xae, 0xce, 0x9f, 0xcf, - 0xaf, 0xdc, 0x5a, 0xc3, 0xa7, 0xff, 0xab, 0x4c, 0x21, 0x5a, 0xda, 0x7f, - 0xb0, 0x3a, 0x7f, 0x32, 0xaf, 0x7c, 0x1b, 0x0e, 0x9f, 0x65, 0xe8, 0x74, - 0x74, 0xed, 0x67, 0x5c, 0xe9, 0xfd, 0xad, 0xa2, 0xfb, 0xc4, 0x3a, 0x39, - 0x47, 0xa6, 0xd3, 0x04, 0xcb, 0x44, 0xbe, 0x8f, 0xcf, 0xef, 0x7b, 0x6d, - 0xa6, 0x3c, 0xe9, 0xfe, 0x0a, 0xd3, 0x3a, 0x41, 0xec, 0xe9, 0xff, 0xfb, - 0xd6, 0xd5, 0xe8, 0x7a, 0x7d, 0x93, 0x91, 0xc7, 0x9d, 0x08, 0x89, 0x31, - 0x38, 0x9f, 0xff, 0x86, 0xaf, 0xef, 0x4a, 0xde, 0x0d, 0x38, 0xf6, 0xb4, - 0xe9, 0xff, 0x55, 0xfd, 0xaf, 0x86, 0x60, 0x1a, 0x20, 0x69, 0xed, 0x6f, - 0x1f, 0xd1, 0x14, 0x82, 0xb9, 0x0c, 0x98, 0x05, 0x43, 0x16, 0x7f, 0xd9, - 0xfa, 0x1e, 0xef, 0xab, 0xda, 0x74, 0xff, 0xff, 0xfd, 0x5a, 0xde, 0x0f, - 0x9e, 0x97, 0xfe, 0x66, 0x9d, 0x57, 0x3d, 0x29, 0x58, 0x36, 0xbc, 0xf1, - 0x05, 0xcf, 0xfb, 0x33, 0xc8, 0x67, 0x3d, 0x3c, 0xf0, 0x78, 0x82, 0xe7, - 0xfe, 0xda, 0x6d, 0x18, 0x75, 0xd3, 0xcf, 0x07, 0x88, 0x2e, 0x7f, 0x32, - 0x0e, 0xba, 0x79, 0xe0, 0xf1, 0x05, 0xcf, 0xca, 0xae, 0x7a, 0x79, 0xe0, - 0xf1, 0x05, 0xcf, 0xff, 0xf6, 0x08, 0xa2, 0xba, 0x5c, 0x36, 0x9f, 0x4f, - 0x36, 0x57, 0x07, 0x88, 0x2e, 0x6b, 0x7a, 0x72, 0x9c, 0xe8, 0x28, 0xfd, - 0x53, 0x10, 0xc5, 0x02, 0x19, 0x56, 0x86, 0xcf, 0xc6, 0x51, 0xcc, 0xfe, - 0x46, 0xf3, 0x7d, 0x5e, 0xd3, 0xa7, 0xb3, 0xfd, 0xe1, 0xd3, 0xff, 0x6d, - 0x36, 0x8c, 0x3a, 0xe9, 0xe7, 0x83, 0xc4, 0x17, 0x3f, 0xce, 0x5c, 0x12, - 0xce, 0x9e, 0x78, 0x3c, 0x41, 0x73, 0xed, 0x5d, 0x95, 0xd0, 0x11, 0x41, - 0xe1, 0x52, 0x7f, 0xf7, 0x40, 0xda, 0x03, 0x6a, 0xfd, 0x3c, 0xf0, 0x78, - 0x82, 0xe7, 0xff, 0xfe, 0x11, 0x45, 0x74, 0xf6, 0xba, 0x5c, 0x36, 0x9f, - 0x4f, 0x36, 0x57, 0x07, 0x88, 0x2e, 0x29, 0x32, 0x3b, 0x50, 0xf1, 0x72, - 0x7f, 0xb6, 0x9f, 0x4f, 0x36, 0x57, 0x07, 0x88, 0x2e, 0x7f, 0xfb, 0x32, - 0xd7, 0xdf, 0x69, 0xcf, 0x2d, 0xf6, 0x2a, 0x7f, 0xd4, 0xf7, 0xfb, 0x7f, - 0x8d, 0x9d, 0x47, 0x88, 0x2e, 0x01, 0x1d, 0x1f, 0x48, 0xba, 0x84, 0xff, - 0x81, 0x3f, 0xac, 0xee, 0xfd, 0x38, 0x3c, 0x41, 0x73, 0xf6, 0xd3, 0x7b, - 0x4e, 0xcd, 0x00, 0x5c, 0xfa, 0xbb, 0xe9, 0xe7, 0x83, 0xc4, 0x17, 0x35, - 0x68, 0x0f, 0xd3, 0x67, 0x51, 0x6a, 0x3b, 0xaf, 0x0c, 0x29, 0xf9, 0x55, - 0xcf, 0x4f, 0x3c, 0x1e, 0x20, 0xb9, 0xff, 0x06, 0xd3, 0xe9, 0xe6, 0xca, - 0xe0, 0xf1, 0x05, 0xcd, 0x5d, 0x31, 0x11, 0xb7, 0x40, 0x9f, 0xde, 0xa2, - 0xb0, 0x6d, 0x79, 0xe2, 0x0b, 0x9f, 0xf5, 0x23, 0xaa, 0x1a, 0xe7, 0x1e, - 0x78, 0x82, 0xd4, 0x78, 0x11, 0xca, 0xf0, 0x2f, 0xcd, 0xfb, 0x35, 0x18, - 0xf9, 0x2f, 0x18, 0xc6, 0xa3, 0x1d, 0xf6, 0x16, 0xdc, 0x37, 0xcf, 0xbb, - 0xbf, 0x7d, 0xb1, 0xa2, 0x0b, 0x5a, 0x23, 0xa7, 0xfd, 0x4f, 0xde, 0x3d, - 0xd9, 0xdb, 0xdb, 0x0e, 0x9c, 0xa6, 0x79, 0xd3, 0xea, 0xe7, 0x7e, 0xf0, - 0x74, 0xbf, 0x87, 0x8a, 0x23, 0x73, 0x93, 0xaa, 0x8e, 0x9d, 0x9f, 0xec, - 0xe9, 0x5a, 0xc6, 0xe7, 0x43, 0xb3, 0xf5, 0x59, 0x9b, 0x6e, 0xb9, 0xd0, - 0x88, 0xb6, 0xc5, 0xf1, 0x27, 0x9d, 0x9f, 0xb0, 0xe9, 0xbb, 0x63, 0xa7, - 0x91, 0x95, 0x47, 0x41, 0xd3, 0xf6, 0x79, 0xd3, 0x7f, 0xb3, 0xa3, 0x93, - 0x72, 0x21, 0x53, 0xff, 0xf9, 0x93, 0x91, 0x6f, 0x43, 0x54, 0x1c, 0xb0, - 0x78, 0x51, 0xd3, 0x76, 0xc7, 0x4c, 0xde, 0x4e, 0x9f, 0xea, 0xd5, 0xd9, - 0x5e, 0x29, 0xc3, 0xa7, 0xf5, 0xeb, 0x69, 0x7f, 0x6c, 0x3a, 0x6e, 0x38, - 0x2a, 0x7f, 0x86, 0x9d, 0x63, 0xee, 0x9c, 0x9d, 0x00, 0x9f, 0xba, 0x0e, - 0x7c, 0x59, 0x4b, 0x1b, 0x21, 0xed, 0x81, 0xdc, 0x16, 0x11, 0x7b, 0x9d, - 0x70, 0x69, 0xe0, 0x62, 0x77, 0x1c, 0x70, 0x54, 0x94, 0x52, 0xcb, 0xf9, - 0xf6, 0x39, 0x99, 0xf2, 0x96, 0x8d, 0xdf, 0x10, 0xbe, 0x9f, 0xd6, 0xe9, - 0xab, 0x75, 0x61, 0xd0, 0xcd, 0x9d, 0x25, 0x46, 0xcf, 0xe5, 0x0a, 0xd3, - 0x04, 0x8c, 0x9b, 0xe9, 0x7b, 0x8f, 0x1b, 0x29, 0x31, 0x42, 0x93, 0x78, - 0xd0, 0x7d, 0x96, 0x02, 0xe9, 0x32, 0x7a, 0x81, 0xb4, 0x74, 0xf5, 0x2a, - 0xb4, 0x74, 0xff, 0xdb, 0xf6, 0xcf, 0x57, 0xb4, 0x0c, 0xf9, 0xd3, 0xd9, - 0x67, 0x87, 0x9d, 0x0c, 0x8a, 0x9b, 0x47, 0xf4, 0x40, 0xec, 0x8d, 0x3f, - 0x0f, 0xbc, 0xab, 0x1e, 0x74, 0xff, 0xf5, 0xaf, 0x16, 0xe8, 0xa1, 0x6f, - 0x3a, 0x4b, 0x0e, 0x9f, 0xd7, 0xd3, 0xaa, 0x1a, 0xe4, 0xe8, 0x64, 0x5a, - 0xa1, 0x76, 0x29, 0xce, 0xce, 0x9e, 0x0e, 0x9f, 0xfe, 0x17, 0xf4, 0xae, - 0x52, 0xf6, 0xeb, 0xdc, 0xb9, 0xd3, 0xee, 0x9b, 0x6f, 0xbc, 0xe8, 0xe8, - 0x89, 0xba, 0x1f, 0xe1, 0x4e, 0x7e, 0xb1, 0xc7, 0xf5, 0x9f, 0xb0, 0xe9, - 0x9f, 0x61, 0xd3, 0xed, 0xd2, 0x3e, 0xe7, 0x4f, 0xff, 0x6d, 0xbc, 0x2f, - 0x43, 0x9d, 0xde, 0xed, 0xd9, 0x53, 0xfb, 0xba, 0xf8, 0x66, 0x01, 0xe2, - 0x04, 0x9d, 0xa4, 0xb0, 0xe8, 0x7a, 0x34, 0x79, 0x26, 0xfa, 0x92, 0x8f, - 0x66, 0x76, 0x79, 0xd3, 0xda, 0xb3, 0x04, 0xe9, 0xeb, 0x6f, 0x9a, 0x3a, - 0x2c, 0x3d, 0xca, 0x19, 0xd9, 0x0c, 0xfe, 0x1c, 0xe2, 0xf7, 0x6e, 0xce, - 0x9d, 0xc7, 0x1c, 0x1e, 0xaf, 0xa9, 0xd8, 0x3c, 0x96, 0xaf, 0xa2, 0xcd, - 0x64, 0x72, 0x89, 0x8e, 0xd7, 0xe7, 0xff, 0xd4, 0x29, 0xe5, 0x77, 0xd6, - 0xfd, 0xc7, 0xbd, 0x8e, 0x8b, 0x0f, 0xef, 0xc9, 0x2c, 0xfb, 0x04, 0x51, - 0x47, 0x47, 0x5b, 0x56, 0x86, 0xf3, 0x6a, 0x87, 0x42, 0x42, 0x6b, 0x23, - 0x42, 0x12, 0x59, 0xf2, 0x69, 0xb5, 0x72, 0xa7, 0x81, 0xb5, 0x72, 0xa6, - 0xe3, 0x82, 0xa1, 0xe7, 0xbd, 0x44, 0xdc, 0x10, 0x4d, 0x5c, 0x14, 0xb3, - 0x5f, 0x3f, 0xfe, 0xad, 0x30, 0x55, 0x0e, 0xb6, 0x8c, 0x36, 0x1d, 0x1d, - 0x9f, 0xb7, 0x04, 0xd3, 0xff, 0xf9, 0x9d, 0x20, 0xf7, 0xd3, 0x57, 0xa0, - 0xde, 0x0e, 0xae, 0x74, 0xfd, 0x6b, 0xf7, 0xeb, 0x7c, 0xe9, 0xff, 0x55, - 0x39, 0xfa, 0xf5, 0x4d, 0x73, 0xa1, 0xc3, 0xed, 0xf9, 0x7c, 0xe7, 0xe7, - 0xce, 0x9f, 0x3e, 0xb5, 0x5c, 0x95, 0x24, 0x70, 0xf0, 0xb4, 0x37, 0x3d, - 0xaf, 0x35, 0xb3, 0xa6, 0xed, 0x8e, 0x9b, 0xb6, 0x3a, 0x7d, 0xeb, 0xe8, - 0x56, 0x86, 0xb3, 0xb1, 0x68, 0x64, 0x46, 0x8a, 0x7c, 0xff, 0xda, 0xdd, - 0x2b, 0xc3, 0x77, 0x56, 0xe8, 0xe9, 0xfd, 0x68, 0x27, 0xfc, 0x37, 0x27, - 0x4f, 0x76, 0xac, 0x7d, 0xcf, 0xf3, 0x48, 0xf3, 0xba, 0xaa, 0xd3, 0xa7, - 0xbb, 0xfa, 0x7c, 0xe8, 0x63, 0xfb, 0xc3, 0xae, 0x07, 0xe7, 0xaf, 0xed, - 0xba, 0x3a, 0x77, 0x1c, 0x70, 0x54, 0xfa, 0xbc, 0x8f, 0xb7, 0x29, 0x65, - 0xfc, 0xfa, 0x97, 0xc7, 0x1c, 0x1d, 0x0c, 0x7c, 0x5a, 0x38, 0x9f, 0xfa, - 0x86, 0xae, 0x1b, 0x40, 0x61, 0x3a, 0x7b, 0x8c, 0x17, 0x9d, 0x3f, 0xda, - 0x6b, 0x7b, 0xcd, 0xed, 0x0e, 0x96, 0xce, 0x8a, 0x3c, 0x90, 0x39, 0x9d, - 0xc7, 0x1c, 0x15, 0x3f, 0x26, 0x79, 0xda, 0x68, 0xa5, 0x97, 0xf3, 0xea, - 0xee, 0xa9, 0xc3, 0xa5, 0x7e, 0x88, 0xa2, 0xf9, 0xf8, 0x9e, 0x4d, 0xeb, - 0xf9, 0x4d, 0x0e, 0xa3, 0x0c, 0x92, 0x6d, 0x3b, 0x81, 0x8e, 0x06, 0x19, - 0x77, 0xfd, 0xe4, 0x95, 0x0c, 0xff, 0x2c, 0xbf, 0x85, 0xae, 0xe3, 0x18, - 0xc2, 0xeb, 0xc2, 0x97, 0x51, 0xec, 0xcf, 0xcc, 0xaf, 0xff, 0x34, 0x74, - 0xff, 0xf2, 0x2a, 0xd7, 0xdf, 0xa5, 0x08, 0xd2, 0x76, 0x74, 0x6c, 0xff, - 0x34, 0x59, 0x25, 0xbb, 0xd0, 0x9f, 0x87, 0x77, 0x65, 0x3d, 0x6a, 0x41, - 0xeb, 0x42, 0xa6, 0x9c, 0xaa, 0xb2, 0x50, 0x2b, 0xe5, 0x55, 0xf3, 0x2d, - 0x2a, 0xab, 0x90, 0x1f, 0x31, 0xdb, 0x84, 0xad, 0xdb, 0x65, 0xa9, 0x24, - 0xad, 0xc7, 0x27, 0xd2, 0xbf, 0x3b, 0x78, 0xa9, 0x5e, 0x5b, 0xa4, 0x2f, - 0x65, 0x61, 0x17, 0xdc, 0xb9, 0x91, 0x9f, 0x5c, 0xbd, 0x6c, 0x25, 0xaa, - 0xd5, 0x43, 0xd8, 0xdf, 0x1d, 0x43, 0xd7, 0x88, 0x64, 0x75, 0x4b, 0x75, - 0xf1, 0x3e, 0xda, 0xed, 0x18, 0xbc, 0x2e, 0x14, 0x4f, 0x0f, 0xc5, 0x00, - 0xd4, 0xfe, 0x5d, 0x7c, 0x33, 0x00, 0xd1, 0x71, 0xcf, 0xe5, 0xd7, 0xc3, - 0x30, 0x0d, 0x17, 0x5c, 0xff, 0xcb, 0xc7, 0xae, 0xbe, 0x19, 0x80, 0x68, - 0x94, 0x61, 0xa1, 0x4b, 0xae, 0xf2, 0x8e, 0x4f, 0x3c, 0x9e, 0x01, 0xe2, - 0x43, 0xd3, 0xae, 0x7f, 0x98, 0xa2, 0xcb, 0xb9, 0xc6, 0x8f, 0x1d, 0x8f, - 0x27, 0xff, 0x2d, 0x58, 0xf5, 0xd7, 0xc3, 0x30, 0x0d, 0x12, 0xd4, 0xfb, - 0xe1, 0x98, 0x06, 0x88, 0xde, 0x7f, 0xd8, 0xf5, 0xd7, 0xc3, 0x30, 0x0d, - 0x12, 0xfc, 0x97, 0x47, 0xf0, 0xa3, 0x19, 0xfc, 0xba, 0xf8, 0x66, 0x01, - 0xa2, 0xab, 0x9f, 0xef, 0x34, 0x35, 0x6e, 0xb1, 0x47, 0x4d, 0xca, 0x1d, - 0x3f, 0x57, 0xc3, 0x30, 0x0d, 0x12, 0x04, 0x74, 0x3c, 0xc5, 0x8b, 0x4f, - 0xaf, 0x83, 0x96, 0x9d, 0x0f, 0x3c, 0xab, 0x49, 0x27, 0xff, 0x53, 0x9b, - 0xc5, 0x6b, 0x6d, 0xaf, 0x54, 0x74, 0x79, 0x4c, 0xf7, 0x21, 0x9f, 0xe0, - 0x8e, 0x7f, 0xe1, 0xab, 0x17, 0xd4, 0xc2, 0x35, 0xa3, 0xa1, 0x67, 0xfb, - 0xf3, 0x99, 0xfc, 0xba, 0xf8, 0x66, 0x01, 0xa2, 0xc8, 0x9f, 0xcb, 0xaf, - 0x86, 0x60, 0x1a, 0x2d, 0x79, 0xfc, 0xba, 0xf8, 0x66, 0x01, 0xa2, 0xe4, - 0x9f, 0x7c, 0x33, 0x00, 0xd1, 0x76, 0x4f, 0xfb, 0x1e, 0xba, 0xf8, 0x66, - 0x01, 0xa2, 0x8e, 0x92, 0xe8, 0xfe, 0x14, 0x63, 0x27, 0x9d, 0x3e, 0xf8, - 0x66, 0x01, 0xa2, 0x95, 0x9f, 0xff, 0xfe, 0xdb, 0x58, 0xdb, 0x47, 0x59, - 0xce, 0xd1, 0x61, 0xb4, 0x73, 0x6d, 0x65, 0x1d, 0x33, 0xd7, 0x48, 0xb0, - 0x70, 0xc6, 0x65, 0xaa, 0xd4, 0x77, 0xe4, 0x30, 0x22, 0xc5, 0xd8, 0x07, - 0xc3, 0x2e, 0xd2, 0x74, 0x8f, 0xd9, 0x44, 0x5d, 0x9e, 0x5c, 0xf3, 0x50, - 0xb4, 0x75, 0x18, 0xb4, 0xff, 0x3d, 0x75, 0xf0, 0xcc, 0x03, 0x44, 0x71, - 0x3f, 0xc8, 0xba, 0xf8, 0x66, 0x01, 0xa2, 0xb5, 0x92, 0xf1, 0x10, 0x7a, - 0x42, 0x9f, 0xfc, 0xb5, 0x63, 0xd7, 0x5f, 0x0c, 0xc0, 0x34, 0x4b, 0x73, - 0x55, 0xa7, 0x4f, 0xee, 0x69, 0x4a, 0x64, 0xb9, 0xd1, 0x69, 0xe4, 0x20, - 0xb4, 0xed, 0xf2, 0xf3, 0xa7, 0x3d, 0x40, 0x74, 0xff, 0xfd, 0xbc, 0xb7, - 0xbe, 0x77, 0x8f, 0xab, 0x8f, 0xb9, 0xe0, 0xe8, 0x34, 0x43, 0x73, 0xfe, - 0xc7, 0xae, 0xbe, 0x19, 0x80, 0x68, 0x98, 0x26, 0x0a, 0x3a, 0x6f, 0x7b, - 0x2a, 0x10, 0xd6, 0x7c, 0x52, 0x7f, 0x0d, 0x6b, 0x4d, 0xfb, 0x9d, 0x25, - 0xb2, 0x72, 0x96, 0x11, 0x72, 0x3b, 0x43, 0x60, 0xbe, 0xa1, 0x7d, 0x39, - 0xf8, 0x20, 0x9c, 0xaf, 0x7e, 0x54, 0xff, 0xb1, 0xeb, 0xaf, 0x86, 0x60, - 0x1a, 0x26, 0x39, 0x2d, 0x0f, 0x91, 0x43, 0xb3, 0xf3, 0x5f, 0xa6, 0xab, - 0x67, 0x4e, 0x61, 0xb0, 0xe9, 0xff, 0xff, 0xe7, 0xdf, 0x75, 0xef, 0x17, - 0xdd, 0x05, 0x5f, 0xa5, 0x5a, 0xfb, 0xa0, 0xa1, 0xd3, 0xc1, 0x98, 0x06, - 0x8a, 0xc6, 0x7f, 0xdd, 0x55, 0xa1, 0xaf, 0x58, 0x74, 0x74, 0x79, 0x4c, - 0xc8, 0x0b, 0xad, 0x1b, 0xfb, 0xfe, 0x8a, 0xe7, 0xff, 0x30, 0xeb, 0xcf, - 0xac, 0x34, 0x0d, 0xf3, 0xa7, 0xfb, 0x9d, 0xd5, 0xed, 0x7b, 0x6c, 0xe9, - 0xfe, 0x6b, 0x5e, 0xe3, 0xf3, 0xf6, 0x1d, 0x14, 0x7e, 0xa8, 0x75, 0x3f, - 0xea, 0xe7, 0xe9, 0xed, 0x9d, 0xdd, 0xe7, 0x4f, 0xff, 0xfc, 0x3e, 0xd9, - 0x41, 0xd0, 0x7d, 0x76, 0xe9, 0x56, 0xbe, 0xbd, 0x1e, 0xee, 0x74, 0xfe, - 0xeb, 0x76, 0x38, 0xfe, 0xb3, 0xf6, 0x1d, 0x3f, 0xfa, 0x9c, 0xde, 0x2b, - 0x5b, 0x6d, 0x7a, 0xa3, 0xa7, 0x6d, 0x17, 0x4a, 0x9d, 0x41, 0x37, 0x70, - 0xbd, 0x12, 0x0d, 0x21, 0x75, 0x3e, 0x78, 0x42, 0x9b, 0xc7, 0x67, 0x4d, - 0xeb, 0x87, 0x4f, 0xb0, 0x6c, 0xf6, 0xe7, 0x47, 0x67, 0xb2, 0x23, 0x37, - 0x18, 0x9f, 0x7b, 0x6d, 0x8d, 0xe4, 0xe9, 0xf2, 0xa8, 0x59, 0xe7, 0x4f, - 0x37, 0xf0, 0x4e, 0x9e, 0xbd, 0xdb, 0xb3, 0xa1, 0x8f, 0x9b, 0x64, 0xbc, - 0x0f, 0xcf, 0x99, 0xfd, 0xfa, 0xf3, 0xa7, 0x30, 0xbc, 0xe8, 0x70, 0xf0, - 0xf4, 0x53, 0x3b, 0x7e, 0x14, 0x74, 0xfc, 0xca, 0xa1, 0x4f, 0x27, 0x4a, - 0xe7, 0x42, 0x1b, 0xcc, 0x2c, 0x9b, 0xb6, 0x2a, 0x6e, 0x38, 0x2a, 0x10, - 0xd7, 0x70, 0x2d, 0x3f, 0xb1, 0xe3, 0x5a, 0xda, 0x14, 0xb3, 0x43, 0x3d, - 0xce, 0x5b, 0x73, 0xa7, 0x30, 0xb8, 0x74, 0xc2, 0xc7, 0x43, 0x86, 0xbf, - 0xe3, 0x73, 0xff, 0x79, 0x41, 0x0b, 0xb2, 0xb2, 0xdd, 0x1d, 0x3b, 0xba, - 0x76, 0x3a, 0x3c, 0x9f, 0x1f, 0xd1, 0x25, 0xe4, 0xe9, 0xbf, 0xe4, 0xe8, - 0x43, 0x55, 0xe0, 0x4a, 0x7f, 0xf9, 0x34, 0xcf, 0x4d, 0x6e, 0xad, 0xd7, - 0xac, 0x74, 0x32, 0x72, 0xd4, 0xa4, 0x90, 0x85, 0xda, 0x76, 0x11, 0x41, - 0xd2, 0x51, 0xd2, 0xde, 0x8b, 0xa7, 0x41, 0x53, 0xf7, 0x6d, 0xba, 0x75, - 0x87, 0x4f, 0xc9, 0xaa, 0xde, 0x79, 0x3a, 0x77, 0x1c, 0x70, 0x54, 0xff, - 0xd4, 0x1c, 0xb5, 0x9e, 0x2b, 0x79, 0x69, 0x4b, 0x2f, 0xe7, 0x93, 0xee, - 0xdc, 0x9d, 0x2f, 0x9d, 0x3e, 0x52, 0x6b, 0xbc, 0x3a, 0x2c, 0x3d, 0xce, - 0xb9, 0x2f, 0xa2, 0x13, 0xf8, 0x12, 0xe3, 0x4e, 0xb0, 0xe9, 0xab, 0x47, - 0x45, 0xa7, 0x8d, 0xb3, 0x19, 0xed, 0x0d, 0x3c, 0xe9, 0xff, 0xc9, 0x7d, - 0xd7, 0x23, 0x4e, 0x86, 0xae, 0x74, 0x7c, 0xfa, 0x74, 0x41, 0x25, 0xb2, - 0xf6, 0xb5, 0x85, 0xfc, 0xc2, 0x4a, 0x9c, 0x90, 0x8f, 0xeb, 0x4a, 0x6e, - 0xdc, 0x7a, 0xd8, 0xcd, 0xd9, 0x43, 0xb8, 0x5c, 0x29, 0x97, 0x85, 0x8e, - 0x9e, 0xfc, 0x42, 0x32, 0x7d, 0xf0, 0xcc, 0x03, 0x45, 0x6f, 0x3f, 0xec, - 0x7a, 0xeb, 0xe1, 0x98, 0x06, 0x89, 0xc2, 0x4b, 0xa3, 0xf8, 0x51, 0x8c, - 0xde, 0xec, 0xe9, 0xf7, 0xc3, 0x30, 0x0d, 0x16, 0x8c, 0xfc, 0xd8, 0x3e, - 0xf3, 0x47, 0x4c, 0x9e, 0x4e, 0x9f, 0xff, 0x58, 0xda, 0x6e, 0x7e, 0xdb, - 0xcb, 0x8d, 0x76, 0x74, 0xff, 0x9a, 0xdc, 0xeb, 0xec, 0x73, 0xaf, 0x61, - 0xd0, 0xc8, 0x9b, 0xda, 0xac, 0xa9, 0xc4, 0x6a, 0x5e, 0x16, 0x52, 0x5b, - 0xbc, 0x9b, 0xb5, 0x0b, 0xa8, 0xc7, 0x71, 0x80, 0x4f, 0x06, 0x60, 0x1a, - 0x2d, 0xa9, 0xfb, 0x6c, 0xa6, 0x4e, 0x4e, 0x95, 0x7c, 0xf5, 0xf4, 0x57, - 0x3f, 0xcb, 0xf3, 0xe7, 0x3f, 0xcf, 0xa2, 0x74, 0x2c, 0xf9, 0x7b, 0x27, - 0x9f, 0xcb, 0xaf, 0x86, 0x60, 0x1a, 0x2e, 0x59, 0xfc, 0xba, 0xf8, 0x66, - 0x01, 0xa2, 0xed, 0x86, 0x6c, 0xd6, 0x2c, 0x28, 0x7c, 0xa2, 0xfe, 0x61, - 0xbb, 0xe6, 0x5e, 0x72, 0x4f, 0xd6, 0xf5, 0xe3, 0x67, 0xdc, 0x73, 0xa3, - 0x18, 0x55, 0xc8, 0xf4, 0x79, 0x3f, 0x97, 0x5f, 0x0c, 0xc0, 0x34, 0x54, - 0xf3, 0x26, 0x8e, 0x9e, 0x0c, 0xc0, 0x34, 0x57, 0x33, 0xf9, 0x75, 0xf0, - 0xcc, 0x03, 0x45, 0x9d, 0x1f, 0x3e, 0x7d, 0x95, 0xcf, 0xff, 0x56, 0x9a, - 0xfd, 0x3d, 0xbe, 0x99, 0xc7, 0x10, 0xe9, 0xff, 0x6d, 0x3f, 0xce, 0xe9, - 0x07, 0xc9, 0xd3, 0xef, 0x86, 0x60, 0x1a, 0x24, 0x29, 0xfe, 0x4b, 0x6f, - 0xa1, 0x65, 0x5c, 0xe9, 0x9e, 0xba, 0x3e, 0x9e, 0xcc, 0x67, 0x9d, 0xed, - 0xb2, 0x8e, 0x9f, 0xd5, 0xbb, 0xde, 0xbf, 0x61, 0xd2, 0x5f, 0x2a, 0x88, - 0x29, 0xf1, 0x08, 0x9c, 0x53, 0xc8, 0x54, 0x5c, 0xbb, 0x44, 0xd3, 0xff, - 0x96, 0xac, 0x7a, 0xeb, 0xe1, 0x98, 0x06, 0x89, 0xf2, 0x01, 0x58, 0xff, - 0x5e, 0x52, 0xe6, 0xdc, 0x27, 0xdf, 0x0c, 0xc0, 0x34, 0x56, 0x53, 0xfe, - 0xc7, 0xae, 0xbe, 0x19, 0x80, 0x68, 0x9b, 0xa6, 0x45, 0xd1, 0xfc, 0x28, - 0xc6, 0x7d, 0xf0, 0xcc, 0x03, 0x44, 0xad, 0x3f, 0xde, 0x76, 0x9d, 0x3d, - 0x0a, 0xb9, 0xd3, 0xe5, 0xab, 0x1e, 0xba, 0x3e, 0xdc, 0x31, 0x9f, 0xf2, - 0x5f, 0xd5, 0x0a, 0x3a, 0xf7, 0x0e, 0x9f, 0xc2, 0xdf, 0xa7, 0x58, 0xa3, - 0xa1, 0xe7, 0xe4, 0x88, 0x13, 0xef, 0x86, 0x60, 0x1a, 0x25, 0xc9, 0xfe, - 0x4c, 0x7e, 0x85, 0x95, 0x73, 0xa7, 0x9d, 0x20, 0xb1, 0xd3, 0xe5, 0xab, - 0x1e, 0xb6, 0x45, 0x4d, 0x10, 0xec, 0xc7, 0x0d, 0xa7, 0xfe, 0x5e, 0x3d, - 0x75, 0xf0, 0xcc, 0x03, 0x44, 0x77, 0x3f, 0xda, 0xdd, 0x3d, 0x78, 0x37, - 0x3a, 0x7e, 0xeb, 0x05, 0x82, 0x84, 0xe9, 0xbd, 0xd9, 0xd3, 0xf3, 0xbe, - 0x35, 0xbc, 0xd1, 0xd3, 0xfa, 0xb8, 0xbb, 0x0e, 0xae, 0x74, 0xfb, 0xe1, - 0x98, 0x06, 0x8a, 0x86, 0x7b, 0x7a, 0xab, 0x0e, 0x9f, 0x55, 0x98, 0x2e, - 0x8e, 0x9f, 0xff, 0xff, 0xcc, 0xfe, 0x9a, 0xda, 0x35, 0xfa, 0x57, 0xa0, - 0xce, 0xba, 0x57, 0xff, 0x4e, 0xbd, 0xcd, 0x9d, 0x14, 0x8e, 0x11, 0x22, - 0xb9, 0x44, 0xff, 0xff, 0x7b, 0x9d, 0x74, 0xb3, 0x78, 0x9a, 0x6d, 0xa6, - 0xaf, 0x5c, 0x9d, 0x25, 0xbb, 0xea, 0x94, 0x5d, 0xe2, 0xee, 0xb0, 0x5e, - 0xc3, 0x0a, 0x32, 0xd4, 0x62, 0x5d, 0x45, 0xd3, 0xef, 0x86, 0x60, 0x1a, - 0x2a, 0x89, 0xff, 0x63, 0xd7, 0x5f, 0x0c, 0xc0, 0x34, 0x4d, 0x72, 0x5d, - 0x1f, 0xc2, 0x8c, 0x67, 0xf2, 0xeb, 0xe1, 0x98, 0x06, 0x8a, 0xb2, 0x7f, - 0xe5, 0xe3, 0xd7, 0x5f, 0x0c, 0xc0, 0x34, 0x48, 0x93, 0xef, 0x86, 0x60, - 0x1a, 0x2d, 0x29, 0xff, 0x63, 0xd7, 0x5f, 0x0c, 0xc0, 0x34, 0x4f, 0xb2, - 0x5d, 0x1f, 0xc2, 0x8c, 0x67, 0xff, 0x2d, 0x58, 0xf5, 0xd7, 0xc3, 0x30, - 0x0d, 0x14, 0x24, 0xfb, 0x69, 0x63, 0x7c, 0xe9, 0xf7, 0xc3, 0x30, 0x0d, - 0x14, 0x7c, 0xff, 0x85, 0x9c, 0x61, 0x67, 0x36, 0xc7, 0x4f, 0xff, 0xd5, - 0xce, 0xdb, 0xc2, 0xf4, 0x39, 0xdd, 0xee, 0xdd, 0x95, 0x3e, 0x5a, 0xb1, - 0xeb, 0x64, 0x79, 0x51, 0x3e, 0x8c, 0x7a, 0x8f, 0x21, 0x99, 0x0d, 0xf6, - 0x46, 0xb0, 0xf5, 0x7a, 0x4d, 0xf3, 0x2a, 0x20, 0x21, 0xf9, 0x69, 0x3b, - 0x87, 0x9b, 0x86, 0x2f, 0x64, 0xfa, 0x8d, 0x16, 0x7f, 0x2e, 0xbe, 0x19, - 0x80, 0x68, 0x88, 0xa7, 0xea, 0xf8, 0x66, 0x01, 0xa2, 0x2b, 0x9f, 0xee, - 0xba, 0xeb, 0xe1, 0x98, 0x06, 0x8a, 0xe2, 0x16, 0x7f, 0x98, 0x6d, 0x3d, - 0x5b, 0xcd, 0x1d, 0x3f, 0xa9, 0x3f, 0xdf, 0x7e, 0xdc, 0xe9, 0x3b, 0xe2, - 0x7a, 0xb7, 0x20, 0x9f, 0xff, 0xb5, 0x74, 0xde, 0x23, 0xd0, 0x75, 0xee, - 0xff, 0x47, 0x4f, 0xbe, 0x19, 0x80, 0x68, 0xa7, 0xa7, 0xea, 0xbf, 0x41, - 0xc7, 0x9d, 0x1d, 0x62, 0x38, 0xd8, 0xb2, 0x96, 0x44, 0xc6, 0x7f, 0xf6, - 0x3d, 0x7c, 0x8e, 0x71, 0x7b, 0xb7, 0x67, 0x42, 0xd1, 0x15, 0xc9, 0xfc, - 0xe5, 0xf3, 0x47, 0x4f, 0x99, 0xfd, 0xfa, 0xf3, 0xa7, 0x83, 0x30, 0x0d, - 0x15, 0x9c, 0x38, 0x7a, 0x9f, 0x29, 0x9f, 0xac, 0x53, 0x0b, 0xee, 0x74, - 0xe6, 0xb1, 0x0e, 0x9f, 0x6b, 0xbf, 0x02, 0xf3, 0xa7, 0x7b, 0x97, 0x3a, - 0x7d, 0x4e, 0x59, 0xef, 0x67, 0x49, 0x74, 0x8d, 0xcf, 0x91, 0xec, 0xb7, - 0x06, 0xc4, 0xab, 0xc0, 0xe4, 0xff, 0xcb, 0xc7, 0xae, 0xbe, 0x19, 0x80, - 0x68, 0x91, 0x67, 0xea, 0xf8, 0x66, 0x01, 0xa2, 0xc9, 0x9f, 0xfd, 0xab, - 0xf8, 0xba, 0xea, 0xc4, 0x17, 0xdc, 0xe8, 0x5a, 0x20, 0xa8, 0xda, 0x7f, - 0x2e, 0xbe, 0x19, 0x80, 0x68, 0xb6, 0x27, 0x55, 0xe8, 0xe9, 0xe0, 0xcc, - 0x03, 0x45, 0xb7, 0x3d, 0x7b, 0x33, 0xe7, 0x47, 0xcf, 0x37, 0x45, 0x72, - 0x5b, 0xd1, 0x13, 0x4c, 0xf3, 0xac, 0xda, 0x1d, 0x3f, 0xee, 0xb3, 0xac, - 0x77, 0x7a, 0xdd, 0x0b, 0x76, 0x74, 0xfc, 0xc2, 0xfe, 0x7d, 0x51, 0xd3, - 0xef, 0x86, 0x60, 0x1a, 0x2f, 0x09, 0xed, 0x75, 0x56, 0xce, 0x9f, 0xf9, - 0xbc, 0x2a, 0xd7, 0xea, 0x87, 0x57, 0x3a, 0x7d, 0x43, 0xdb, 0xb3, 0x1d, - 0x3e, 0x6f, 0x1e, 0xe5, 0xce, 0x9d, 0xa6, 0xec, 0xe9, 0x2f, 0xac, 0x4e, - 0x87, 0xad, 0x43, 0x96, 0x27, 0x51, 0x75, 0xa6, 0x3b, 0x24, 0xed, 0x18, - 0x4a, 0x74, 0x53, 0x39, 0x2a, 0xd3, 0xa7, 0xdf, 0x0c, 0xc0, 0x34, 0x5e, - 0x93, 0xfe, 0x1c, 0xd3, 0xdb, 0xce, 0x92, 0xc3, 0xa7, 0xd4, 0xad, 0xe7, - 0x27, 0x49, 0x7c, 0xa2, 0xca, 0x86, 0xfc, 0x18, 0xbb, 0x1f, 0xc3, 0x32, - 0x5c, 0xec, 0x85, 0xc5, 0x47, 0xc6, 0x04, 0x89, 0x1a, 0x67, 0xd7, 0x15, - 0x0c, 0xfe, 0xc8, 0x86, 0x18, 0xbe, 0xc7, 0x93, 0xc4, 0x68, 0xb3, 0x7b, - 0xb3, 0xa7, 0xab, 0x79, 0xa3, 0xa7, 0xf5, 0x27, 0xfb, 0xef, 0xdb, 0x9d, - 0x27, 0x7c, 0x4f, 0x56, 0xe4, 0x13, 0xe4, 0xd3, 0x5b, 0x61, 0xd3, 0xef, - 0x86, 0x60, 0x1a, 0x22, 0x39, 0xff, 0xed, 0xfb, 0x7b, 0xd2, 0x86, 0x9d, - 0x74, 0x67, 0x74, 0x74, 0xff, 0x9e, 0xd6, 0x7e, 0xb5, 0xa4, 0xd1, 0xd3, - 0xfd, 0x5f, 0xab, 0xd6, 0x0d, 0x87, 0x4f, 0xff, 0xf3, 0x6f, 0x13, 0x4d, - 0xb1, 0xad, 0x6d, 0x37, 0x49, 0xc1, 0xd3, 0x58, 0xa2, 0xa6, 0xe3, 0x82, - 0xa7, 0xfc, 0xb0, 0xda, 0x39, 0xb6, 0xb1, 0x7d, 0x9a, 0xfe, 0x05, 0xe7, - 0x9d, 0x36, 0x98, 0xe8, 0x79, 0xfd, 0x22, 0xc4, 0xfd, 0xd7, 0x1a, 0xde, - 0x68, 0xe9, 0xf9, 0xbc, 0xd0, 0xa7, 0x93, 0xa7, 0xea, 0xd3, 0xb6, 0xab, - 0x67, 0x45, 0x22, 0x30, 0x4b, 0xee, 0x5d, 0x3f, 0xff, 0x02, 0xff, 0x82, - 0x9a, 0x5f, 0xdb, 0x43, 0x9d, 0x9d, 0x0e, 0xf2, 0xbf, 0xce, 0xb1, 0xb1, - 0x8b, 0x28, 0xa0, 0x0c, 0x6d, 0x59, 0x43, 0xef, 0x9b, 0x64, 0x61, 0x7a, - 0x85, 0x6b, 0xa2, 0xe9, 0xf7, 0xc3, 0x30, 0x0d, 0x11, 0x74, 0xfb, 0x5d, - 0xf8, 0x17, 0x95, 0x25, 0xd1, 0xed, 0xe1, 0x8c, 0x2d, 0x32, 0xe7, 0xc6, - 0x11, 0x3f, 0xf2, 0xb1, 0xeb, 0xaf, 0x86, 0x60, 0x1a, 0x26, 0x69, 0xfb, - 0xad, 0x1d, 0xdb, 0xbf, 0x76, 0xd1, 0xd3, 0xad, 0x6b, 0x9d, 0x38, 0x11, - 0x47, 0x4d, 0xd5, 0xd6, 0xce, 0x9f, 0xb5, 0x56, 0x57, 0x6e, 0x1d, 0x1d, - 0x6c, 0xf3, 0x9c, 0x1f, 0x9f, 0x06, 0x6d, 0x1c, 0x3a, 0x7f, 0xfd, 0xdd, - 0xaf, 0xdf, 0xad, 0xf5, 0xed, 0x03, 0x3e, 0x74, 0xff, 0xce, 0xc9, 0xa4, - 0x04, 0xe7, 0x54, 0x07, 0x4f, 0xff, 0xf7, 0xb8, 0x20, 0x35, 0xce, 0xfd, - 0xe9, 0xb6, 0x7f, 0xda, 0xc3, 0xa1, 0x93, 0x04, 0xa5, 0x7d, 0xa2, 0x4f, - 0xff, 0xb9, 0x41, 0xb2, 0xae, 0x99, 0xb5, 0xf1, 0xc7, 0x05, 0x4f, 0xd6, - 0xbe, 0xfd, 0xfa, 0xe1, 0xd3, 0xc1, 0x98, 0x06, 0x8b, 0x3e, 0x7f, 0xc9, - 0xb6, 0x7a, 0x69, 0xb5, 0x73, 0xa7, 0xff, 0x93, 0xfb, 0xce, 0x94, 0xe8, - 0x6a, 0xf4, 0x27, 0x4e, 0xe3, 0x8e, 0x0a, 0x9f, 0xf6, 0x3e, 0xe3, 0x41, - 0xcd, 0x7c, 0xa5, 0x97, 0xf3, 0xfc, 0xdb, 0x4e, 0x47, 0x31, 0xc3, 0xa7, - 0xf9, 0x07, 0x9f, 0x1c, 0xfb, 0xab, 0x9d, 0x00, 0xa8, 0x79, 0xc5, 0x8f, - 0x99, 0x28, 0xaf, 0x67, 0x9d, 0xb7, 0x69, 0x2d, 0xd1, 0xbc, 0xff, 0x7f, - 0x38, 0xda, 0x37, 0xd8, 0xe9, 0xff, 0xff, 0xfa, 0xab, 0xbb, 0xd5, 0x0f, - 0x9f, 0x1f, 0x16, 0xad, 0xae, 0xe3, 0x56, 0x2a, 0x94, 0x74, 0xeb, 0xb5, - 0x87, 0x4e, 0xea, 0xad, 0x9d, 0x0f, 0x46, 0x1d, 0xe1, 0x13, 0xa1, 0xc9, - 0xdb, 0xf7, 0x83, 0xa7, 0x77, 0xe8, 0x1d, 0x3b, 0x55, 0xe0, 0xe8, 0xe4, - 0xf6, 0x2d, 0x1e, 0x41, 0xd9, 0xfb, 0xe8, 0xea, 0x86, 0xe7, 0x4f, 0xb6, - 0x2d, 0x5f, 0x32, 0x7f, 0xc9, 0xf7, 0xd7, 0xec, 0xf7, 0x39, 0x34, 0x41, - 0xab, 0x34, 0xb3, 0xec, 0x04, 0x53, 0x1d, 0x3f, 0x3f, 0x63, 0x96, 0xe8, - 0xe9, 0x50, 0x1e, 0x88, 0x92, 0x4f, 0xfd, 0x43, 0x6e, 0xab, 0xe9, 0x66, - 0x28, 0xe9, 0x90, 0x4e, 0x9f, 0xb3, 0x8d, 0x56, 0xf4, 0xc7, 0xaf, 0xe5, - 0x0e, 0x19, 0x3c, 0x27, 0xa9, 0x54, 0x2b, 0x85, 0xf2, 0x7e, 0xfd, 0x73, - 0x7d, 0xb1, 0xd3, 0xff, 0xfb, 0xd1, 0xcf, 0x3d, 0x3c, 0x0e, 0x6a, 0xe9, - 0x6e, 0xd3, 0x83, 0xa7, 0xfc, 0xaa, 0xd5, 0xfc, 0x5f, 0x1f, 0x47, 0x4f, - 0xd7, 0xbb, 0x7f, 0x4c, 0x72, 0xcd, 0xfc, 0xf6, 0xe9, 0x1d, 0x1d, 0x3f, - 0x5d, 0x3f, 0x5e, 0xfc, 0xe8, 0x44, 0x45, 0xec, 0xf3, 0x44, 0x53, 0x29, - 0xdf, 0x34, 0x5f, 0x93, 0xff, 0x3f, 0x5e, 0xbd, 0xea, 0xd6, 0x99, 0x47, - 0x4f, 0xfc, 0x94, 0x35, 0x57, 0xe8, 0xfb, 0xa8, 0xe8, 0xb5, 0x11, 0x37, - 0x46, 0x99, 0x1c, 0x3a, 0x76, 0x92, 0xc3, 0xa7, 0x0b, 0x01, 0xd1, 0xd0, - 0xf2, 0xd4, 0x2c, 0x23, 0x90, 0xc9, 0xbf, 0xf2, 0x5f, 0x50, 0xb1, 0xc6, - 0xf9, 0xff, 0xff, 0x9d, 0x9b, 0x68, 0xa5, 0xb8, 0xfc, 0xff, 0x8d, 0xa5, - 0xb7, 0x04, 0xb0, 0xe9, 0xfb, 0x3e, 0xdb, 0xf1, 0xc9, 0xd3, 0xdc, 0x65, - 0x5c, 0xe9, 0xfe, 0x7a, 0xb1, 0xfa, 0xbb, 0x79, 0x3a, 0x18, 0xf6, 0xf0, - 0x86, 0x7a, 0xae, 0x82, 0x74, 0x62, 0x32, 0x46, 0x11, 0x5e, 0x90, 0x4f, - 0x78, 0xf7, 0x2e, 0x74, 0xfc, 0xed, 0xaa, 0xc1, 0x03, 0xa7, 0xfa, 0xfd, - 0xa5, 0xb6, 0xbe, 0xb4, 0x74, 0x6c, 0xfa, 0x34, 0x5b, 0x0c, 0x8a, 0xea, - 0x84, 0x64, 0xce, 0x7a, 0x74, 0x94, 0x74, 0x5a, 0x6a, 0x1d, 0xc1, 0x89, - 0xfd, 0x99, 0x6b, 0xc5, 0xb9, 0x3a, 0x7f, 0xf0, 0xa3, 0x5c, 0x71, 0xfd, - 0x2f, 0x5f, 0x3a, 0x7f, 0xff, 0xdb, 0x4b, 0x75, 0x56, 0xeb, 0xff, 0x6d, - 0x77, 0xe0, 0x5f, 0xba, 0x3a, 0x7b, 0x9e, 0x70, 0x4e, 0x9f, 0xf6, 0x6c, - 0x13, 0x3a, 0x5f, 0x36, 0x74, 0x32, 0x6e, 0x1c, 0x93, 0xd1, 0x90, 0x24, - 0x23, 0x86, 0xc8, 0xa7, 0xfe, 0xa1, 0xb7, 0x55, 0xf4, 0xb3, 0x14, 0x74, - 0xfa, 0xb4, 0xf5, 0x6c, 0xe9, 0xf5, 0xb7, 0x16, 0x51, 0xd0, 0xc8, 0x91, - 0xba, 0x1f, 0xa4, 0xf3, 0x77, 0xb3, 0xa7, 0xeb, 0x1c, 0x7f, 0x59, 0xfb, - 0x0e, 0x9f, 0xde, 0x77, 0x5a, 0xda, 0x68, 0xe9, 0x93, 0xe7, 0x47, 0x5b, - 0x3f, 0xf4, 0x36, 0xd9, 0xa4, 0xff, 0xdc, 0xb7, 0x3f, 0x6d, 0x20, 0x27, - 0x27, 0x4f, 0xdb, 0xf6, 0xc7, 0x36, 0x87, 0x47, 0x27, 0xe9, 0xb4, 0x49, - 0x2f, 0xad, 0xb6, 0x41, 0x0e, 0xf1, 0xfb, 0xbb, 0x1c, 0x66, 0x8b, 0x0a, - 0x79, 0x8c, 0xaa, 0xa5, 0x26, 0xf9, 0x76, 0xb6, 0x1f, 0x49, 0x08, 0xd7, - 0x23, 0xf2, 0xfa, 0x02, 0x8b, 0x77, 0x2a, 0xc3, 0x10, 0x7b, 0x8d, 0x04, - 0x61, 0xc5, 0x78, 0xef, 0xb5, 0x0e, 0x6e, 0x0c, 0x3a, 0xa1, 0x2d, 0xe2, - 0x15, 0x10, 0xb6, 0xcf, 0x93, 0x75, 0x92, 0xac, 0xff, 0xe5, 0xab, 0x1e, - 0xba, 0xf8, 0x66, 0x01, 0xa2, 0x6c, 0x9f, 0xcb, 0xaf, 0x86, 0x60, 0x1a, - 0x2a, 0xd9, 0xfc, 0xf7, 0xfb, 0xa1, 0x67, 0x9d, 0x3d, 0x5b, 0xcd, 0x1d, - 0x27, 0x7e, 0x8f, 0x4c, 0x4c, 0xe7, 0xdf, 0x0c, 0xc0, 0x34, 0x56, 0x93, - 0xff, 0xc0, 0xdf, 0xae, 0xf1, 0x58, 0xf6, 0x40, 0x3a, 0x7f, 0xf9, 0xf7, - 0xa1, 0x65, 0x65, 0x6b, 0x4c, 0xa3, 0xa6, 0xd6, 0x99, 0x12, 0xf8, 0x97, - 0x3f, 0x99, 0xd7, 0x8d, 0x0b, 0x76, 0x74, 0xfd, 0x65, 0x6d, 0x29, 0x47, - 0x4f, 0xf5, 0x3b, 0x0b, 0x71, 0x6b, 0xee, 0x74, 0xfe, 0x7d, 0x6b, 0x07, - 0xbf, 0x4e, 0x92, 0xfa, 0xc4, 0xfc, 0x68, 0xad, 0x21, 0x91, 0xb2, 0xdc, - 0x36, 0x12, 0xcd, 0x1e, 0x4f, 0xe5, 0xd7, 0xc3, 0x30, 0x0d, 0x16, 0x04, - 0xfb, 0xe1, 0x98, 0x06, 0x89, 0xd6, 0x7f, 0xff, 0x6d, 0xac, 0xe6, 0x94, - 0xbb, 0xde, 0xb6, 0x97, 0xf6, 0xc3, 0xa7, 0xcb, 0x56, 0x3d, 0x74, 0x89, - 0x57, 0x0c, 0x67, 0xf3, 0xee, 0xbf, 0x3e, 0x59, 0x47, 0x4f, 0xbe, 0x19, - 0x80, 0x68, 0xb6, 0x67, 0xfd, 0xdb, 0x5d, 0x7b, 0x40, 0xcf, 0x9d, 0x25, - 0xd1, 0xf7, 0x61, 0x8c, 0xf0, 0x66, 0x01, 0xa2, 0xe6, 0x92, 0x8e, 0x8f, - 0x9b, 0xbe, 0x0a, 0xe6, 0x71, 0x47, 0x49, 0x74, 0x6e, 0x78, 0x22, 0x9f, - 0xcb, 0xaf, 0x86, 0x60, 0x1a, 0x2e, 0xf9, 0xe5, 0xf9, 0xe7, 0xb3, 0xa1, - 0x9b, 0xa5, 0xda, 0xad, 0x03, 0x80, 0xca, 0xd5, 0x34, 0x95, 0x01, 0xf7, - 0x15, 0x43, 0x47, 0x10, 0x3b, 0x85, 0x2d, 0xe1, 0x35, 0xa2, 0x7f, 0x07, - 0x93, 0xeb, 0xdd, 0x58, 0xf3, 0xa7, 0xfe, 0xb4, 0x3d, 0xcb, 0x75, 0x54, - 0x3e, 0x4e, 0x9c, 0x38, 0xb6, 0x3e, 0xdd, 0x13, 0xcf, 0xe1, 0xb2, 0x9d, - 0xb4, 0xde, 0x4e, 0x9f, 0x7c, 0x33, 0x00, 0xd1, 0x2b, 0xcf, 0xf8, 0x73, - 0x8e, 0x76, 0xd6, 0x57, 0x07, 0x4f, 0xff, 0xcf, 0xa4, 0xee, 0x94, 0x9a, - 0xbb, 0x2b, 0x2d, 0xd1, 0xd3, 0xde, 0xe7, 0xde, 0x74, 0xff, 0xfe, 0x4d, - 0x62, 0xb0, 0x7b, 0xdf, 0x18, 0x36, 0x02, 0x58, 0x74, 0x72, 0x88, 0x2c, - 0x22, 0x8e, 0x53, 0x3f, 0xa4, 0x0d, 0xc3, 0x72, 0x76, 0x3d, 0x6c, 0x9e, - 0xed, 0x1b, 0xde, 0x37, 0x09, 0xda, 0x6e, 0x4a, 0x9f, 0xfd, 0xbc, 0x4d, - 0x33, 0xd3, 0xf6, 0x7b, 0xd9, 0x53, 0xfb, 0x01, 0x7c, 0xfd, 0xdc, 0x5b, - 0x1f, 0x3d, 0xc7, 0x24, 0xb0, 0x56, 0x14, 0xa9, 0x41, 0xce, 0xa1, 0x5b, - 0x3f, 0xf9, 0x6a, 0xc7, 0xae, 0xbe, 0x19, 0x80, 0x68, 0x98, 0x67, 0xff, - 0x0b, 0x3a, 0x16, 0xb5, 0x7d, 0x6d, 0xdd, 0xdd, 0xe7, 0x4f, 0xfe, 0xfe, - 0x76, 0xbf, 0x3a, 0x7f, 0x0d, 0x77, 0x9d, 0x35, 0x2f, 0x94, 0x52, 0xf8, - 0x57, 0x9f, 0xf9, 0xdf, 0xab, 0x5f, 0xee, 0x68, 0x59, 0xe7, 0x4f, 0xe6, - 0xcb, 0x35, 0xe7, 0x3e, 0x74, 0xfb, 0x3e, 0xfc, 0x51, 0xd0, 0x27, 0xb5, - 0xe9, 0xa4, 0xfc, 0xa6, 0xa1, 0xd7, 0x51, 0xd2, 0xb9, 0xd3, 0xe6, 0xa1, - 0xd7, 0x51, 0xd3, 0xf6, 0xd3, 0x57, 0xcb, 0x7a, 0x1f, 0x33, 0x85, 0xca, - 0x10, 0x9f, 0xff, 0xf0, 0xd7, 0x0e, 0xda, 0xad, 0xf4, 0x1a, 0xb1, 0x28, - 0x6d, 0x7d, 0xce, 0x9f, 0xfe, 0x6d, 0x0e, 0x77, 0xba, 0x4e, 0x7d, 0xd5, - 0xce, 0x9f, 0x9d, 0x78, 0xd0, 0xb7, 0x67, 0x4f, 0xfe, 0x6d, 0x76, 0xcf, - 0xab, 0x75, 0x67, 0xbc, 0x1d, 0x0c, 0x7f, 0xe8, 0x63, 0x3f, 0x5d, 0x3c, - 0xab, 0x34, 0x74, 0xff, 0xff, 0xbf, 0x4e, 0x98, 0x75, 0xd3, 0xc0, 0xb6, - 0xf1, 0x34, 0xda, 0xb9, 0xd2, 0xab, 0x51, 0x39, 0xf2, 0xe9, 0xff, 0xf6, - 0xc6, 0xb5, 0xb4, 0xab, 0x75, 0x4e, 0x9a, 0xe7, 0x4e, 0x6e, 0xfc, 0x1d, - 0x14, 0x7e, 0x62, 0xab, 0x3d, 0x9e, 0x39, 0xa3, 0xa4, 0xbe, 0xb1, 0x71, - 0x6b, 0x98, 0x51, 0x84, 0x22, 0x1c, 0x55, 0xfb, 0x86, 0xe1, 0x9e, 0x30, - 0xbc, 0xd4, 0x27, 0x3d, 0x20, 0x9f, 0x7c, 0x33, 0x00, 0xd1, 0x57, 0x4f, - 0xf3, 0xd7, 0x5f, 0x0c, 0xc0, 0x34, 0x47, 0x92, 0x5d, 0x1f, 0x9e, 0x18, - 0xcf, 0xe5, 0xd7, 0xc3, 0x30, 0x0d, 0x16, 0x0c, 0xfe, 0x5d, 0x7c, 0x33, - 0x00, 0xd1, 0x65, 0x4f, 0xe5, 0xd7, 0xc3, 0x30, 0x0d, 0x16, 0x9c, 0xfe, - 0xab, 0xf4, 0xff, 0xfd, 0xd9, 0xd3, 0xc1, 0x98, 0x06, 0x8b, 0x72, 0x7f, - 0xe6, 0xaf, 0xd0, 0xf4, 0xdd, 0x5b, 0xc1, 0xd1, 0xf3, 0xf0, 0xb9, 0x5c, - 0xff, 0x30, 0xfa, 0xa6, 0xbe, 0x90, 0xe9, 0xfd, 0x99, 0x67, 0x2d, 0x5f, - 0x3a, 0x7f, 0xd8, 0xf5, 0xd7, 0xc3, 0x30, 0x0d, 0x14, 0x3c, 0xff, 0xca, - 0xce, 0x5b, 0x9d, 0xa0, 0xa2, 0x8e, 0x9f, 0xfb, 0xd7, 0xef, 0x3f, 0x6e, - 0x99, 0x2c, 0x3a, 0x7f, 0xde, 0xff, 0xbf, 0xe0, 0xea, 0xbb, 0x3a, 0x7e, - 0xbe, 0x5b, 0x7d, 0x21, 0xd3, 0xf0, 0xf5, 0x95, 0xf6, 0xb9, 0xd3, 0xff, - 0xf5, 0x73, 0xb6, 0xf0, 0xbd, 0x0e, 0x77, 0x7b, 0xb7, 0x65, 0x49, 0x6f, - 0x55, 0xf9, 0x50, 0xa6, 0x42, 0x27, 0x0d, 0xd4, 0x65, 0x88, 0xfd, 0xa1, - 0xdd, 0x1b, 0x48, 0x1e, 0x96, 0xf5, 0x18, 0x4f, 0xe5, 0xd7, 0xc3, 0x30, - 0x0d, 0x17, 0x9c, 0x33, 0x2e, 0x6d, 0xe8, 0xbc, 0xc3, 0xe2, 0xa7, 0x22, - 0xed, 0x8c, 0x67, 0xe4, 0xca, 0x3c, 0xd9, 0xe0, 0xcb, 0x38, 0x75, 0x0a, - 0x89, 0xfc, 0xba, 0xf8, 0x66, 0x01, 0xa2, 0x96, 0x9f, 0xcb, 0xaf, 0x86, - 0x60, 0x1a, 0x2c, 0x29, 0xfc, 0xba, 0xf8, 0x66, 0x01, 0xa2, 0xcb, 0x9e, - 0x5f, 0x9e, 0xb4, 0x77, 0x47, 0x4e, 0x5f, 0x85, 0x1d, 0x3c, 0x0b, 0x6b, - 0x81, 0xe7, 0xfa, 0x63, 0x3f, 0xf9, 0x6a, 0xc7, 0xae, 0xbe, 0x19, 0x80, - 0x68, 0xa3, 0x27, 0xf2, 0xd9, 0xd3, 0x7d, 0xbb, 0x3a, 0x1e, 0x9e, 0x17, - 0xcf, 0x14, 0x79, 0x90, 0x8b, 0xb9, 0xc6, 0x94, 0xe7, 0xfe, 0x5e, 0x3d, - 0x75, 0xf0, 0xcc, 0x03, 0x44, 0x73, 0x3f, 0xf9, 0x6a, 0xc7, 0xae, 0xbe, - 0x19, 0x80, 0x68, 0x9c, 0xa7, 0xf2, 0xeb, 0xe1, 0x98, 0x06, 0x8b, 0x32, - 0x7f, 0xbb, 0xfb, 0x6b, 0x79, 0x6b, 0xce, 0x9f, 0xd5, 0x7f, 0xfe, 0xad, - 0xb9, 0xd2, 0x5b, 0x1f, 0x6b, 0xce, 0xa7, 0xf2, 0xeb, 0xe1, 0x98, 0x06, - 0x8b, 0x76, 0x7f, 0xf2, 0xd5, 0x8f, 0x5d, 0x7c, 0x33, 0x00, 0xd1, 0x48, - 0x4f, 0xfc, 0xbc, 0x7a, 0xeb, 0xe1, 0x98, 0x06, 0x89, 0x4a, 0x2c, 0x54, - 0x98, 0xe2, 0x6a, 0x94, 0xfb, 0x85, 0x48, 0x93, 0xe8, 0xf1, 0xd9, 0x4e, - 0x7f, 0xd8, 0xf5, 0xd7, 0xc3, 0x30, 0x0d, 0x13, 0xb4, 0xff, 0xf9, 0x39, - 0xf5, 0x4c, 0xed, 0x9c, 0x8b, 0x0d, 0x01, 0xd2, 0x5a, 0x91, 0x3b, 0x88, - 0xf3, 0xff, 0x62, 0xb7, 0x41, 0x9b, 0x6f, 0x0f, 0x3a, 0x7f, 0xe1, 0xad, - 0xe5, 0x95, 0x71, 0xcb, 0x4e, 0x9b, 0xa9, 0x7c, 0xa2, 0x16, 0xe8, 0x70, - 0xa4, 0x70, 0x75, 0x42, 0xb6, 0x7d, 0xf0, 0xcc, 0x03, 0x44, 0x59, 0x3f, - 0xec, 0x7a, 0xeb, 0xe1, 0x98, 0x06, 0x89, 0x76, 0x7f, 0xfe, 0xae, 0x76, - 0xde, 0x17, 0xa1, 0xce, 0xef, 0x76, 0xec, 0xa9, 0x2e, 0x91, 0xac, 0xa3, - 0x1e, 0xa4, 0x79, 0xff, 0xcb, 0x56, 0x3d, 0x75, 0xf0, 0xcc, 0x03, 0x44, - 0xc5, 0x3e, 0xf8, 0x66, 0x01, 0xa2, 0xa9, 0x95, 0x1d, 0x14, 0x78, 0x1e, - 0x4c, 0x67, 0xff, 0xff, 0x7f, 0x37, 0x6b, 0xeb, 0x4b, 0xde, 0x5f, 0xe9, - 0xc6, 0xb6, 0x9f, 0x79, 0xd0, 0xb4, 0x4e, 0x61, 0x1c, 0xff, 0xe5, 0xab, - 0x1e, 0xba, 0xf8, 0x66, 0x01, 0xa2, 0x74, 0x9f, 0xc9, 0x9f, 0x67, 0xe3, - 0xa3, 0xa7, 0xce, 0x33, 0x8d, 0x73, 0xa7, 0xee, 0x29, 0x1d, 0x50, 0x9d, - 0x08, 0x7a, 0xb7, 0x28, 0x9c, 0x9b, 0x63, 0x96, 0x68, 0x67, 0xfe, 0xf6, - 0xfa, 0x6b, 0x57, 0xeb, 0x88, 0xa3, 0xa1, 0x47, 0xe5, 0xb2, 0xa9, 0xff, - 0x63, 0xd7, 0x5f, 0x0c, 0xc0, 0x34, 0x4e, 0xf3, 0xed, 0x7b, 0x8a, 0x42, - 0xa4, 0xbe, 0x53, 0xaa, 0xa8, 0xc6, 0x94, 0x45, 0x88, 0xf3, 0xff, 0x96, - 0xac, 0x7a, 0xeb, 0xe1, 0x98, 0x06, 0x8a, 0x16, 0x7f, 0xf2, 0xd5, 0x8f, - 0x5d, 0x7c, 0x33, 0x00, 0xd1, 0x49, 0x4f, 0xff, 0xea, 0xba, 0xfc, 0x53, - 0x9b, 0xc5, 0x6b, 0x6d, 0xaf, 0x54, 0x74, 0x58, 0xb9, 0xb2, 0xf3, 0x80, - 0x8c, 0xbf, 0xe4, 0x4a, 0x8f, 0xf7, 0xb4, 0x9f, 0x54, 0xfa, 0x94, 0xe7, - 0xf2, 0xeb, 0xe1, 0x98, 0x06, 0x88, 0x92, 0x7f, 0xf2, 0xd5, 0x8f, 0x5d, - 0x7c, 0x33, 0x00, 0xd1, 0x2f, 0x4f, 0xbf, 0xda, 0x92, 0xe7, 0x4e, 0xed, - 0xb4, 0x74, 0xff, 0xd8, 0xe5, 0xd9, 0xd6, 0x6d, 0xad, 0x70, 0xe8, 0x44, - 0x45, 0xb8, 0x51, 0xf1, 0xc9, 0xfe, 0x4c, 0x1f, 0x74, 0xe3, 0x79, 0x3a, - 0x7d, 0xf0, 0xcc, 0x03, 0x45, 0x2f, 0x3e, 0x1d, 0x59, 0x5c, 0x1d, 0x3f, - 0xdd, 0xdf, 0xed, 0x6b, 0xd1, 0x47, 0x4f, 0xf6, 0x59, 0xd2, 0xcf, 0x5c, - 0x6e, 0xb9, 0xd3, 0x53, 0xd8, 0xff, 0x3d, 0x3a, 0x99, 0xf4, 0x74, 0xe6, - 0xee, 0xe7, 0x47, 0x26, 0xc7, 0x81, 0x59, 0xff, 0x91, 0x59, 0xcf, 0x87, - 0x1e, 0xc3, 0x69, 0xd3, 0xd7, 0x4e, 0x34, 0x74, 0x6c, 0xfa, 0x74, 0x8f, - 0x3f, 0xd9, 0xbc, 0x71, 0x3e, 0xd6, 0x1d, 0x3e, 0x76, 0x45, 0x35, 0xce, - 0x9f, 0x63, 0xaa, 0xfd, 0xce, 0x93, 0x72, 0x7a, 0x2a, 0x29, 0x92, 0xd9, - 0x57, 0xe7, 0x26, 0x14, 0x75, 0x69, 0x8b, 0x90, 0xa4, 0xda, 0xf6, 0x42, - 0x32, 0xe4, 0x5a, 0x84, 0x4c, 0xfe, 0x5d, 0x7c, 0x33, 0x00, 0xd1, 0x4e, - 0x4f, 0xf9, 0x3f, 0x97, 0xdd, 0x50, 0x81, 0xd3, 0xfe, 0xad, 0xb7, 0xe9, - 0x7c, 0x71, 0xc1, 0x53, 0x27, 0x07, 0x4d, 0x62, 0xf9, 0x44, 0x87, 0x51, - 0xd3, 0xb2, 0x04, 0xfb, 0xe1, 0x98, 0x06, 0x8a, 0xf2, 0x7f, 0xfe, 0xae, - 0x76, 0xde, 0x17, 0xa1, 0xce, 0xef, 0x76, 0xec, 0xa9, 0x2e, 0x91, 0x1f, - 0xd4, 0x63, 0x3f, 0xf2, 0xf1, 0xeb, 0xaf, 0x86, 0x60, 0x1a, 0x24, 0x79, - 0xc9, 0xdb, 0x1d, 0x38, 0x29, 0x45, 0x2c, 0xbb, 0x9f, 0x7c, 0x33, 0x00, - 0xd1, 0x24, 0x4f, 0x2f, 0x1e, 0xb6, 0x3d, 0xaa, 0x29, 0x9f, 0xf9, 0x78, - 0xf5, 0xd7, 0xc3, 0x30, 0x0d, 0x12, 0x54, 0xfb, 0xe1, 0x98, 0x06, 0x8b, - 0xc6, 0x7d, 0x7b, 0xea, 0x80, 0xe9, 0xfe, 0x7a, 0xeb, 0xe1, 0x98, 0x06, - 0x89, 0x36, 0x4b, 0xa4, 0x4c, 0xfc, 0xc7, 0x09, 0xa1, 0x99, 0x11, 0x16, - 0x1e, 0x3e, 0x5e, 0xd7, 0x30, 0x95, 0x48, 0x66, 0x39, 0x0d, 0x35, 0x15, - 0xee, 0x18, 0x5a, 0x37, 0xf6, 0x1c, 0xd0, 0xd1, 0xe2, 0x46, 0xd9, 0x1d, - 0x93, 0xe5, 0x3d, 0x73, 0x28, 0xc2, 0xaf, 0x1d, 0xc3, 0xcc, 0xa5, 0xe0, - 0xb4, 0x9a, 0xf6, 0xd2, 0x04, 0x92, 0x79, 0x4b, 0xaf, 0x1d, 0xe3, 0x95, - 0x9d, 0x8f, 0xe9, 0x78, 0x4a, 0xc5, 0x35, 0x86, 0xe7, 0x8e, 0x32, 0xb4, - 0x76, 0xee, 0x5f, 0x73, 0xb9, 0x0b, 0x41, 0xa4, 0x84, 0x5e, 0x94, 0x5f, - 0xab, 0x40, 0x93, 0xed, 0x3f, 0x6d, 0xd4, 0xa7, 0x1e, 0x25, 0x54, 0x75, - 0x47, 0xdb, 0xe2, 0x77, 0x69, 0xda, 0x92, 0x1b, 0x00, + 0x61, 0x86, 0xcd, 0xe1, 0x13, 0xa8, 0xca, 0xfa, 0x8f, 0x7d, 0x42, 0xd2, + 0x7e, 0x76, 0x2e, 0x45, 0x9c, 0x5a, 0x7a, 0xb7, 0x9a, 0x5a, 0x4e, 0xfd, + 0x1e, 0x80, 0x98, 0x4f, 0xbe, 0x19, 0x80, 0xa8, 0xb5, 0xa7, 0xfd, 0x8f, + 0x3d, 0x7c, 0x33, 0x01, 0x51, 0x41, 0xc8, 0xfd, 0x62, 0x28, 0xe8, 0xac, + 0xc6, 0x33, 0xff, 0x8e, 0x6c, 0x79, 0xeb, 0xe1, 0x98, 0x0a, 0x8a, 0x2e, + 0x7f, 0x1e, 0xbe, 0x19, 0x80, 0xa8, 0xba, 0xa1, 0xec, 0xb1, 0x70, 0x84, + 0x71, 0x13, 0x1a, 0x16, 0xdb, 0x9f, 0x10, 0xee, 0x3d, 0x4b, 0x9d, 0x69, + 0x4e, 0x7d, 0xf0, 0xcc, 0x05, 0x44, 0x43, 0x3b, 0x75, 0xca, 0xd2, 0x3d, + 0x1e, 0x6d, 0xa6, 0x33, 0xf8, 0xf5, 0xf0, 0xcc, 0x05, 0x44, 0x6d, 0x3f, + 0x8f, 0x5f, 0x0c, 0xc0, 0x54, 0x53, 0x73, 0xf8, 0xf5, 0xf0, 0xcc, 0x05, + 0x45, 0x41, 0x3f, 0x8f, 0x5f, 0x0c, 0xc0, 0x54, 0x54, 0xd3, 0xef, 0x86, + 0x60, 0x2a, 0x2b, 0x09, 0xf1, 0x71, 0xcf, 0x9f, 0x5a, 0x7f, 0x9e, 0x7a, + 0xf8, 0x66, 0x02, 0xa2, 0x3f, 0x9d, 0x4d, 0x62, 0xd2, 0x3d, 0x22, 0xe0, + 0x0c, 0x70, 0xa8, 0x50, 0xa7, 0xff, 0x1c, 0xd8, 0xf3, 0xd7, 0xc3, 0x30, + 0x15, 0x13, 0x7c, 0xff, 0xc6, 0xc7, 0x9e, 0xbe, 0x19, 0x80, 0xa8, 0x9f, + 0xa7, 0xdd, 0x6d, 0xdf, 0xea, 0xab, 0x56, 0x96, 0xd6, 0x87, 0x74, 0x78, + 0xde, 0x1b, 0x4f, 0xf7, 0x5a, 0xdb, 0xcd, 0x6b, 0x33, 0x85, 0xa7, 0xdd, + 0x3d, 0xff, 0x01, 0x69, 0xf7, 0x58, 0xee, 0xfb, 0xf6, 0xcb, 0x4f, 0xff, + 0x33, 0x33, 0x33, 0x33, 0x33, 0x5b, 0x75, 0xa7, 0xdf, 0x2b, 0x30, 0xc9, + 0x4d, 0xc7, 0x09, 0x45, 0x1b, 0xfe, 0x09, 0xe5, 0xe2, 0x47, 0x34, 0x30, + 0xc8, 0xca, 0xbc, 0x2a, 0x67, 0xff, 0xea, 0x35, 0xf5, 0xfc, 0xb3, 0x9d, + 0xb5, 0xf5, 0xe6, 0xd6, 0x9f, 0x60, 0x6c, 0xbe, 0xb4, 0xff, 0xff, 0xe1, + 0xcf, 0x65, 0xf6, 0x7f, 0x4d, 0x91, 0xb9, 0x6e, 0x9d, 0x5e, 0x6c, 0xbe, + 0xb4, 0xf6, 0x3c, 0xad, 0x5a, 0x39, 0x4c, 0x93, 0xeb, 0xdb, 0x25, 0x18, + 0x40, 0x4f, 0xff, 0x9d, 0x9a, 0xd7, 0xe0, 0xf7, 0xd3, 0xb2, 0xf9, 0x7b, + 0x5a, 0x7a, 0xc3, 0x13, 0xd6, 0x9f, 0x5c, 0x7c, 0xc7, 0xad, 0x3f, 0xb6, + 0xc6, 0x3f, 0x7d, 0xb2, 0xd2, 0xfb, 0x1f, 0xed, 0x11, 0x11, 0x3c, 0xff, + 0x9a, 0xde, 0x7d, 0x37, 0x5f, 0x7e, 0x5d, 0x69, 0x75, 0xd6, 0x9a, 0xf4, + 0xb4, 0x11, 0xa9, 0xec, 0x52, 0x7f, 0xee, 0x5b, 0x59, 0x7a, 0xde, 0xc8, + 0xcb, 0x4e, 0xd1, 0x38, 0xb4, 0x31, 0xef, 0xdd, 0x0e, 0x19, 0x5d, 0x59, + 0x46, 0x96, 0xe2, 0x1f, 0xe1, 0xb4, 0x63, 0x21, 0x70, 0xd4, 0x20, 0x27, + 0x39, 0xe8, 0xcb, 0x4f, 0xf5, 0x6a, 0xf5, 0xad, 0xd7, 0x6b, 0x46, 0x1e, + 0xb8, 0x8f, 0xcd, 0x82, 0xb4, 0x7c, 0xda, 0x18, 0x82, 0x77, 0x1c, 0x70, + 0xb4, 0xf5, 0x82, 0x4c, 0x91, 0xcb, 0xf9, 0xad, 0x7a, 0xd3, 0xfb, 0xdb, + 0x6a, 0xfb, 0xcf, 0x16, 0x98, 0x81, 0x69, 0x5a, 0xc7, 0xc1, 0xec, 0x5f, + 0x46, 0xb0, 0xc9, 0x83, 0x6d, 0x03, 0xc8, 0x47, 0xcf, 0xfd, 0x67, 0x9d, + 0xd0, 0xf8, 0xe3, 0x6b, 0x16, 0x9f, 0xf9, 0xb7, 0xeb, 0x9d, 0x15, 0x38, + 0xc6, 0x5a, 0x79, 0xb5, 0x70, 0x54, 0x41, 0xd3, 0xf6, 0x6d, 0xba, 0xfe, + 0x3d, 0x68, 0xfa, 0x3a, 0xcc, 0x8f, 0xa4, 0x67, 0x45, 0xb3, 0x7f, 0x95, + 0xa6, 0xe3, 0x85, 0xa1, 0xe6, 0xbf, 0x81, 0x79, 0xeb, 0xb1, 0x3a, 0x48, + 0xe6, 0x8a, 0x7d, 0x7f, 0x5c, 0xf7, 0x75, 0xa0, 0x8f, 0x7b, 0xd1, 0x94, + 0xee, 0x38, 0xe1, 0x28, 0x48, 0xe5, 0xfc, 0xf1, 0x70, 0x4e, 0x25, 0x00, + 0x6e, 0xc8, 0x66, 0x09, 0x38, 0xad, 0xc3, 0xb8, 0x5f, 0x67, 0x09, 0x5d, + 0x69, 0xee, 0x70, 0x7b, 0x5a, 0x7f, 0xe6, 0x1e, 0xc5, 0xad, 0x71, 0x87, + 0xb5, 0xa0, 0x91, 0x01, 0xd8, 0xd5, 0xc8, 0xa7, 0xcd, 0x5f, 0xd9, 0x2d, + 0x3d, 0xcd, 0x1b, 0xae, 0xb4, 0x38, 0x79, 0x6e, 0x89, 0x67, 0xed, 0x53, + 0x82, 0xc6, 0x5c, 0x40, 0x53, 0xec, 0x1e, 0x76, 0xca, 0x88, 0x08, 0xe6, + 0xe6, 0x7e, 0xfb, 0x3f, 0x2d, 0xe1, 0x69, 0xfe, 0x6f, 0xd9, 0xd2, 0x9c, + 0x23, 0x2d, 0x3c, 0x66, 0xa3, 0x2d, 0x3f, 0xac, 0xb6, 0xed, 0xce, 0x89, + 0x69, 0xc5, 0x6d, 0xd6, 0x93, 0x61, 0xe8, 0xf6, 0x6b, 0x3f, 0xbe, 0xe5, + 0xc8, 0x74, 0x4b, 0x4f, 0x5b, 0xdf, 0xd9, 0x29, 0xb8, 0xe1, 0x28, 0x63, + 0x77, 0xc1, 0x1c, 0xfd, 0x9f, 0x7b, 0xc4, 0x92, 0x39, 0xa1, 0x86, 0x55, + 0xcd, 0x4f, 0x64, 0xbd, 0xf4, 0x3d, 0x97, 0x61, 0xd8, 0xb8, 0xe8, 0x9f, + 0xc8, 0x47, 0x4f, 0xbc, 0xd7, 0x99, 0xe9, 0x51, 0x03, 0xcf, 0xfb, 0x7e, + 0x58, 0xdd, 0x1b, 0x4d, 0xca, 0xd3, 0xb3, 0xf6, 0x2d, 0x37, 0x1c, 0x2d, + 0x3f, 0xbe, 0x54, 0xeb, 0xd3, 0xce, 0x06, 0xd3, 0x81, 0xc8, 0xe5, 0x18, + 0x7f, 0x76, 0x9f, 0xf8, 0x6b, 0xde, 0xf1, 0xfe, 0xb2, 0xd6, 0x5a, 0x18, + 0xfa, 0xa8, 0x92, 0x7f, 0xf5, 0x18, 0xd8, 0xfa, 0xf8, 0x66, 0x02, 0xa2, + 0x18, 0x8d, 0x9f, 0x90, 0x90, 0x4f, 0xbe, 0x19, 0x80, 0xa8, 0x82, 0xa7, + 0x6d, 0x8c, 0xb4, 0x51, 0xe6, 0x11, 0x8c, 0xf6, 0xae, 0xdd, 0xa5, 0x3b, + 0x3f, 0x62, 0x53, 0xde, 0x0e, 0x7b, 0x4a, 0x7f, 0x15, 0x95, 0xab, 0xb7, + 0x69, 0x42, 0x53, 0xf5, 0x03, 0x6d, 0x8c, 0x94, 0xdc, 0x70, 0x94, 0xfc, + 0x2c, 0x36, 0x17, 0xd2, 0x8a, 0x4c, 0x2c, 0x08, 0x8c, 0x39, 0xb2, 0x3e, + 0xcc, 0xc4, 0x2b, 0x82, 0xaf, 0x43, 0x13, 0x17, 0xd2, 0x39, 0xf9, 0xcb, + 0x1e, 0x9e, 0x26, 0xe3, 0x9e, 0x9f, 0xf3, 0x3f, 0x06, 0xaf, 0xf6, 0xba, + 0xd3, 0xfd, 0xad, 0xb3, 0xae, 0x5b, 0xb6, 0x5a, 0x7f, 0x9a, 0xd7, 0xf5, + 0x30, 0x51, 0x96, 0x86, 0x3f, 0x5d, 0x9d, 0xcf, 0xff, 0xce, 0x66, 0x3f, + 0x37, 0xd2, 0xac, 0xf3, 0x5e, 0x67, 0xa5, 0x45, 0xf7, 0x3e, 0x2d, 0x0d, + 0x3d, 0x69, 0xff, 0x09, 0x3f, 0x5b, 0xaf, 0x95, 0xd6, 0x9f, 0xda, 0xef, + 0xd0, 0xbf, 0x74, 0xb8, 0x80, 0x67, 0x67, 0xde, 0xb8, 0x80, 0x62, 0x8f, + 0xab, 0xc4, 0x29, 0xb1, 0xeb, 0x88, 0x06, 0x7b, 0x06, 0xd7, 0xae, 0x20, + 0x19, 0xfc, 0x41, 0xba, 0xef, 0xb6, 0x5c, 0x40, 0x33, 0x88, 0x79, 0x5c, + 0x40, 0x31, 0xca, 0x2d, 0xcc, 0x45, 0xb2, 0xe7, 0x47, 0xf3, 0xbe, 0xda, + 0x5c, 0x40, 0x30, 0xb8, 0x80, 0x66, 0x63, 0x2e, 0x20, 0x18, 0xe4, 0xdc, + 0x90, 0xbc, 0xf1, 0x1b, 0x96, 0x5c, 0x40, 0x33, 0xb5, 0x80, 0xb8, 0x80, + 0x67, 0xfc, 0x38, 0xf3, 0xec, 0x83, 0x3e, 0xb8, 0x80, 0x66, 0xce, 0x57, + 0x10, 0x0c, 0xfe, 0x1c, 0xe2, 0xf7, 0x6e, 0xd7, 0x10, 0x0c, 0xf8, 0xbd, + 0xe0, 0xf6, 0xb8, 0x80, 0x66, 0x2b, 0xae, 0x20, 0x18, 0xf9, 0xeb, 0xe8, + 0xd6, 0x7d, 0xa1, 0x6b, 0x5e, 0xa8, 0x80, 0x66, 0xed, 0x97, 0x10, 0x09, + 0xcd, 0xa4, 0xf8, 0x98, 0xd9, 0xca, 0xe2, 0x01, 0x9e, 0xf3, 0x04, 0x17, + 0x10, 0x0c, 0xe6, 0xf8, 0x2e, 0x20, 0x19, 0xff, 0x55, 0xb7, 0xe5, 0xa8, + 0x7b, 0xba, 0xe2, 0x01, 0x9f, 0x79, 0x8f, 0x7b, 0x2e, 0x20, 0x18, 0xa4, + 0x40, 0x6d, 0x32, 0x6f, 0xf6, 0xb8, 0x80, 0x61, 0xea, 0xa4, 0x39, 0x23, + 0xa8, 0x4b, 0x92, 0xb6, 0xcc, 0xfb, 0x33, 0xb9, 0x6e, 0xa1, 0x4f, 0xe1, + 0x14, 0xfa, 0xb5, 0x7c, 0xb5, 0x71, 0x00, 0xcf, 0xee, 0x58, 0x1c, 0xfb, + 0x69, 0x71, 0x00, 0xf2, 0x6d, 0x27, 0x7d, 0xb8, 0x5c, 0x40, 0x30, 0x07, + 0xf5, 0xf5, 0x19, 0xe2, 0x17, 0xdd, 0x71, 0x00, 0xcf, 0xd8, 0xe3, 0xea, + 0xd7, 0xae, 0x20, 0x18, 0xa4, 0x44, 0xf6, 0x43, 0xe1, 0x6c, 0xff, 0x6d, + 0xae, 0x7b, 0xf9, 0xfe, 0xd7, 0x10, 0x0c, 0x89, 0x71, 0x00, 0xcd, 0x96, + 0x72, 0x7c, 0x9b, 0x48, 0x9b, 0xfd, 0xae, 0x20, 0x19, 0xf6, 0x6a, 0xe5, + 0x6a, 0xe2, 0x01, 0x9f, 0x88, 0x7c, 0x7d, 0x5d, 0x71, 0x00, 0xc3, 0x22, + 0x44, 0x49, 0x34, 0x69, 0x1c, 0xb2, 0x03, 0x6a, 0x1b, 0x2e, 0x20, 0x7d, + 0x87, 0x64, 0x38, 0x5d, 0xd9, 0x3d, 0xe5, 0x6c, 0x6a, 0x3c, 0x2e, 0xa8, + 0x4a, 0xfa, 0x86, 0x04, 0xec, 0xc0, 0x54, 0x40, 0x27, 0x45, 0xf4, 0xf7, + 0xb7, 0x77, 0xc9, 0x96, 0x9f, 0xf9, 0xe3, 0x41, 0xb2, 0xef, 0xbf, 0x1c, + 0x5a, 0x6e, 0xd9, 0x29, 0x7b, 0x4a, 0x76, 0xda, 0xc5, 0xa6, 0xe3, 0x84, + 0xa0, 0x8f, 0x73, 0xae, 0x2c, 0xe0, 0x97, 0x03, 0x93, 0x8c, 0x57, 0x48, + 0xe7, 0x83, 0x16, 0x32, 0xc2, 0x1e, 0x4a, 0x14, 0x97, 0x12, 0x38, 0xc2, + 0xbe, 0xe1, 0xc7, 0x3f, 0x8b, 0x5e, 0x9d, 0x3a, 0x6b, 0xad, 0x3f, 0x7d, + 0xc7, 0xb7, 0xec, 0x5a, 0x7f, 0xcf, 0xbf, 0x41, 0xa3, 0x37, 0xfd, 0xad, + 0x3f, 0xf7, 0xf7, 0x94, 0xf6, 0xff, 0x7e, 0x8c, 0xb4, 0xfd, 0xeb, 0x8f, + 0x95, 0x6d, 0x29, 0xe7, 0x37, 0x8e, 0x2d, 0x3e, 0xa7, 0x1e, 0xd6, 0xad, + 0x3d, 0x42, 0xcf, 0x4a, 0x3e, 0x7d, 0x42, 0x46, 0xec, 0x51, 0x0c, 0x9c, + 0x05, 0x17, 0x92, 0x0e, 0xd1, 0xb2, 0x13, 0x33, 0xc4, 0x3a, 0xba, 0xd3, + 0xbc, 0x77, 0x2e, 0xb4, 0xff, 0xdd, 0x9a, 0x83, 0x65, 0xce, 0xfc, 0xf6, + 0xb4, 0xfe, 0xe5, 0xad, 0xbd, 0x5b, 0xa5, 0xa7, 0xf9, 0xb4, 0x40, 0x5c, + 0xb6, 0x96, 0x9b, 0x57, 0xa3, 0xeb, 0xf9, 0xac, 0xfe, 0x7d, 0x5f, 0xd5, + 0xf5, 0x4b, 0x43, 0x26, 0x6c, 0x44, 0x59, 0x0b, 0x3f, 0x0b, 0x67, 0xd8, + 0xeb, 0x9e, 0x59, 0x69, 0xaf, 0x75, 0xa7, 0x71, 0xc7, 0x0b, 0x4d, 0xde, + 0x24, 0x72, 0xfe, 0x3e, 0x7b, 0x57, 0x35, 0x9f, 0xf5, 0x5c, 0x73, 0xdb, + 0x82, 0x4e, 0x2d, 0x3b, 0x3b, 0xa4, 0xa1, 0xe9, 0x80, 0x1a, 0x10, 0x9b, + 0x22, 0xea, 0x3f, 0x9f, 0xda, 0x1a, 0xb7, 0xbf, 0x4f, 0x5a, 0x7f, 0x86, + 0x9d, 0x51, 0xf8, 0xe3, 0x84, 0xa7, 0x1b, 0x34, 0xb4, 0x6c, 0xf5, 0xdd, + 0x1e, 0x4f, 0xa9, 0xc7, 0xb3, 0xd6, 0x86, 0x4c, 0x78, 0x91, 0xb2, 0x11, + 0xba, 0x24, 0x9f, 0x9d, 0xc2, 0xfb, 0x7c, 0x56, 0x9f, 0xfd, 0x5c, 0xe1, + 0xaa, 0xd7, 0xd7, 0x75, 0xca, 0xd3, 0x6f, 0x16, 0x99, 0xcb, 0xad, 0x3e, + 0xa7, 0x44, 0x3c, 0xd1, 0xac, 0xf4, 0x2b, 0x1d, 0x11, 0x6e, 0x77, 0x79, + 0xee, 0x6b, 0x78, 0xb4, 0xff, 0xcd, 0x42, 0xfd, 0xd0, 0x8b, 0x70, 0xb4, + 0x8b, 0xe8, 0x86, 0x12, 0x5d, 0x10, 0xc5, 0x8d, 0xc4, 0x03, 0xe3, 0xd7, + 0xe6, 0x51, 0x8f, 0xb2, 0xf0, 0x85, 0x81, 0x10, 0xfe, 0x96, 0xec, 0x66, + 0x8d, 0xc7, 0x71, 0xda, 0x60, 0xc6, 0xad, 0xa9, 0x4b, 0xfe, 0x20, 0x3a, + 0x8d, 0xb6, 0x7f, 0xab, 0xe2, 0xda, 0x7d, 0x6d, 0x69, 0xf8, 0x7b, 0xae, + 0x71, 0xeb, 0x4f, 0xb1, 0xfd, 0x39, 0x25, 0xa7, 0xde, 0x9c, 0x7b, 0x75, + 0xd2, 0x86, 0x45, 0xd5, 0x1b, 0x6c, 0xb7, 0xd1, 0x4c, 0xff, 0xde, 0xc7, + 0xcc, 0xf5, 0x57, 0x26, 0x15, 0xa7, 0x75, 0x17, 0x2b, 0x47, 0xcf, 0x90, + 0xc8, 0xb2, 0xf4, 0xa8, 0x81, 0x65, 0xa5, 0x50, 0x29, 0x22, 0xd1, 0xbc, + 0xe0, 0x7e, 0x7f, 0xc5, 0xd5, 0xb2, 0xf4, 0x7e, 0xfb, 0x64, 0xa7, 0xff, + 0xf6, 0xdb, 0xfd, 0xd3, 0xa2, 0xbd, 0xe8, 0x43, 0x07, 0xb5, 0xa7, 0xfe, + 0xbe, 0x5b, 0xd0, 0xcd, 0x43, 0xae, 0xa5, 0xa3, 0x68, 0xa8, 0xd3, 0x04, + 0x32, 0x61, 0xe5, 0x0e, 0xc9, 0xff, 0xfe, 0xfd, 0x94, 0x4e, 0x66, 0x3e, + 0xec, 0x6e, 0x76, 0xc2, 0x0b, 0x4e, 0xb0, 0x5e, 0xb4, 0x32, 0xa3, 0xc3, + 0x2f, 0x6e, 0x33, 0x6c, 0x27, 0xf1, 0x96, 0x7f, 0x3d, 0xca, 0x1c, 0xdd, + 0x2d, 0x3f, 0xfb, 0xe0, 0x34, 0xe8, 0x69, 0xbe, 0xd7, 0x5a, 0x7f, 0x63, + 0x9b, 0xa3, 0x55, 0xd6, 0x8a, 0x3f, 0x97, 0x48, 0xf3, 0xf1, 0x7b, 0xd5, + 0x51, 0x96, 0x9f, 0x57, 0x25, 0xfb, 0xad, 0x3f, 0xfd, 0x7d, 0x5a, 0x05, + 0xbe, 0x8e, 0xd5, 0xb2, 0x32, 0xd2, 0x6b, 0x0f, 0xef, 0x82, 0x78, 0x24, + 0x7a, 0x6c, 0x8f, 0x50, 0xa8, 0x9f, 0xf0, 0x97, 0xab, 0x69, 0xd5, 0xad, + 0xe9, 0x69, 0xdc, 0xe7, 0xd6, 0x9f, 0x77, 0x83, 0x4e, 0xcb, 0x43, 0x1e, + 0x2f, 0x83, 0x93, 0x8d, 0x6b, 0x8b, 0x4f, 0xfc, 0x6b, 0x99, 0xb9, 0x6f, + 0xf8, 0xdd, 0xad, 0x0c, 0x7c, 0x84, 0x3d, 0x0c, 0xac, 0x05, 0xf1, 0xcf, + 0x51, 0xa5, 0xe1, 0x13, 0xa8, 0x43, 0x4f, 0xfe, 0x79, 0x6e, 0x9c, 0x27, + 0x3c, 0x76, 0xf2, 0xeb, 0x4f, 0x9a, 0xc6, 0x76, 0x65, 0xa7, 0xef, 0x3d, + 0x6e, 0xad, 0xba, 0xd3, 0xff, 0xff, 0xef, 0xb6, 0x87, 0x00, 0xae, 0xe1, + 0x7c, 0x1a, 0xfa, 0x6b, 0x5b, 0xd5, 0x5d, 0x69, 0xff, 0xff, 0xff, 0x5e, + 0xf5, 0xad, 0xe1, 0xaf, 0xff, 0x95, 0xba, 0xcc, 0xf7, 0x54, 0xe7, 0x9a, + 0x6e, 0x2d, 0x65, 0xa1, 0x93, 0x1f, 0xc8, 0x40, 0xcf, 0x77, 0x96, 0xdd, + 0x69, 0xb8, 0xe1, 0x68, 0xb9, 0xbb, 0xe0, 0x8e, 0x7c, 0x5b, 0xca, 0xda, + 0x47, 0x34, 0x51, 0x6a, 0xa8, 0x2d, 0xa8, 0x3b, 0x85, 0x23, 0x1a, 0x85, + 0xe1, 0x09, 0x3b, 0x8e, 0x38, 0x4a, 0x79, 0xfa, 0xa0, 0x48, 0xe5, 0xfc, + 0xfa, 0xb9, 0x2e, 0xee, 0xbb, 0xbf, 0xa5, 0x9f, 0x3e, 0x41, 0x2f, 0x9b, + 0xf7, 0x5a, 0x73, 0xa6, 0x05, 0xa1, 0x8d, 0x91, 0x0b, 0x4f, 0xc3, 0x6d, + 0xdc, 0xad, 0x2d, 0x3f, 0xfc, 0x3a, 0x72, 0xbf, 0x58, 0x66, 0xd9, 0x72, + 0xb4, 0xfa, 0xce, 0xb9, 0x55, 0xab, 0x4f, 0x8a, 0xed, 0x61, 0x97, 0x67, + 0xec, 0xf9, 0xb3, 0xfd, 0xf8, 0xbb, 0x3f, 0x66, 0xc7, 0xae, 0xcf, 0xd9, + 0xef, 0x1f, 0x57, 0x5d, 0x9f, 0xb1, 0xc9, 0xe8, 0x89, 0x14, 0xf9, 0xaa, + 0xf4, 0x2b, 0xb3, 0xf6, 0x17, 0x67, 0xec, 0xd9, 0xa5, 0xd9, 0xfa, 0x62, + 0xde, 0x4f, 0x13, 0xf9, 0xf1, 0x22, 0x7a, 0xba, 0x8b, 0xb5, 0xd9, 0xfb, + 0x0b, 0xb3, 0xf6, 0x6e, 0xd9, 0x76, 0x7e, 0xcf, 0xf5, 0x77, 0x9f, 0xa7, + 0x55, 0xca, 0xec, 0xfd, 0x9f, 0xab, 0x65, 0x7f, 0x2c, 0x5d, 0x9f, 0xb1, + 0xda, 0x29, 0x44, 0x8e, 0xe8, 0xf3, 0xdf, 0xb1, 0xb4, 0xbb, 0x3f, 0x61, + 0x76, 0x7e, 0xd1, 0xaf, 0x9b, 0x8e, 0x17, 0x67, 0xec, 0x3d, 0x58, 0xa7, + 0x26, 0x95, 0x08, 0x6b, 0x61, 0x37, 0xf2, 0x83, 0x18, 0xde, 0x17, 0x9a, + 0x5f, 0xe0, 0x9a, 0x7a, 0x9e, 0xde, 0xd3, 0x67, 0xe8, 0xe8, 0x91, 0x9f, + 0xf5, 0x07, 0x35, 0xfe, 0x33, 0x6e, 0x2d, 0x33, 0xec, 0x4a, 0x2c, 0x44, + 0xc5, 0xa8, 0x42, 0x7f, 0x1f, 0x5c, 0x9a, 0xc9, 0xc6, 0x99, 0xff, 0xf3, + 0xfe, 0xce, 0xb1, 0xc6, 0xe7, 0x6c, 0x6c, 0x71, 0x69, 0xfc, 0xed, 0x97, + 0x2b, 0xb9, 0x4b, 0x45, 0xa8, 0x8d, 0xfa, 0xc4, 0x32, 0xf3, 0x5b, 0xd6, + 0x28, 0x7c, 0x8b, 0xb2, 0x73, 0xa3, 0xc8, 0x5d, 0x4f, 0xfb, 0xdb, 0x5a, + 0x2d, 0xbd, 0xf8, 0x0b, 0x4f, 0xc3, 0x9e, 0xf7, 0x8f, 0x5a, 0x77, 0x1c, + 0x70, 0x94, 0xef, 0x4d, 0xda, 0x47, 0x2f, 0xe7, 0xfc, 0x38, 0xff, 0x5f, + 0xa7, 0x59, 0xf5, 0xa7, 0xf8, 0x73, 0xbe, 0x8f, 0x6e, 0xed, 0x5a, 0x39, + 0x4c, 0xd4, 0xc8, 0x1d, 0xa6, 0x09, 0x6e, 0x90, 0x27, 0xfc, 0x22, 0x5e, + 0x3b, 0x97, 0xea, 0x6d, 0x2d, 0x3b, 0x8e, 0x38, 0x4c, 0x42, 0x09, 0xf7, + 0xc3, 0x30, 0x13, 0x10, 0x80, 0xe6, 0xb6, 0x77, 0x1c, 0x70, 0x98, 0x83, + 0xd0, 0x98, 0x83, 0xc7, 0x35, 0xb3, 0x31, 0xa9, 0x12, 0xe0, 0xdf, 0x3e, + 0xd3, 0x69, 0x8c, 0xb4, 0xf0, 0x93, 0x7b, 0x5a, 0x77, 0xa6, 0xed, 0x68, + 0xb0, 0xdf, 0x98, 0x86, 0x7c, 0x0d, 0xb6, 0x32, 0x53, 0xe1, 0xc1, 0x1a, + 0x4a, 0x6a, 0x04, 0xa6, 0xe3, 0x84, 0xa2, 0x8f, 0xd2, 0xe4, 0xba, 0x23, + 0xe0, 0x52, 0x7f, 0x0f, 0xa6, 0xef, 0x74, 0xec, 0x91, 0xcd, 0xe4, 0x32, + 0x6f, 0xc4, 0xcb, 0x90, 0xd2, 0x9f, 0xf9, 0xbb, 0xbd, 0x57, 0x38, 0x39, + 0xed, 0x69, 0xff, 0xf5, 0xaf, 0xbf, 0x0d, 0xfd, 0xb1, 0x6d, 0x84, 0x96, + 0x8d, 0xa2, 0x63, 0x11, 0x27, 0xf5, 0xfd, 0x1a, 0xfc, 0x65, 0xab, 0x43, + 0x2e, 0x11, 0xd2, 0x61, 0x46, 0x13, 0xf8, 0xea, 0xb2, 0x19, 0x77, 0x22, + 0x9d, 0xc7, 0x1c, 0x25, 0x3d, 0xde, 0x0f, 0x29, 0x1c, 0xbf, 0x9f, 0xbd, + 0x57, 0xea, 0x9c, 0x5a, 0x1e, 0x7b, 0xf7, 0x31, 0x9f, 0xfe, 0x1b, 0x7a, + 0x5b, 0xdb, 0x08, 0x65, 0x83, 0x8b, 0x4f, 0xff, 0xff, 0xf6, 0xaf, 0xea, + 0xfd, 0x37, 0x85, 0xa2, 0xd8, 0x17, 0x47, 0x96, 0xf0, 0x74, 0xfa, 0xfd, + 0x2d, 0x3f, 0xfd, 0x4c, 0x7e, 0x45, 0xbc, 0x0a, 0xf6, 0x5f, 0x5a, 0x79, + 0xdb, 0x7d, 0xba, 0x5a, 0x1e, 0x7e, 0xf8, 0x9f, 0x3f, 0xf9, 0xf5, 0xfe, + 0xcc, 0x57, 0xf5, 0x76, 0xa5, 0xa7, 0x8b, 0x9a, 0x32, 0xd0, 0xca, 0x83, + 0x5e, 0x45, 0x4a, 0x39, 0x18, 0x68, 0x90, 0xf8, 0x97, 0x3f, 0x75, 0xee, + 0x43, 0x6b, 0xd6, 0x9f, 0xf6, 0x7f, 0xa8, 0xb7, 0x59, 0x6f, 0x6b, 0x4f, + 0xfa, 0xf7, 0x6f, 0xe9, 0x8f, 0xc9, 0x2d, 0x3f, 0xe1, 0xc7, 0x37, 0x9f, + 0xf9, 0x72, 0xb4, 0x52, 0x3b, 0x80, 0xc4, 0x90, 0x4c, 0x7d, 0x3c, 0xff, + 0x54, 0xe2, 0xd3, 0xef, 0xf3, 0x54, 0x2b, 0x4f, 0xfd, 0xd7, 0x2a, 0xdb, + 0x3a, 0xbe, 0xda, 0xd5, 0xa3, 0x0f, 0xbe, 0xe4, 0xd3, 0xfd, 0x43, 0xfa, + 0xbd, 0x16, 0xd6, 0x9f, 0xfe, 0xad, 0x5e, 0x9c, 0xdb, 0x3a, 0xad, 0xed, + 0x96, 0x9e, 0xad, 0x15, 0xd6, 0x9f, 0x9d, 0xd3, 0x82, 0xef, 0x59, 0xe2, + 0xd1, 0x73, 0xdb, 0xd1, 0x04, 0x72, 0x99, 0x18, 0x10, 0x89, 0xae, 0xa1, + 0x57, 0x3f, 0xfc, 0x57, 0xae, 0x75, 0x72, 0xf7, 0xbc, 0x12, 0x5a, 0x7f, + 0xff, 0x0e, 0xab, 0x64, 0xda, 0x2e, 0xd9, 0xe7, 0xe3, 0x8e, 0x12, 0x9e, + 0xe6, 0xab, 0xda, 0x53, 0xd9, 0xde, 0x69, 0x69, 0xcf, 0x1f, 0x15, 0x10, + 0xcc, 0xee, 0x38, 0xe1, 0x29, 0xd4, 0x20, 0x91, 0xcb, 0xf9, 0xff, 0x55, + 0x95, 0xce, 0x3c, 0x5a, 0xc5, 0xa3, 0xb3, 0xe6, 0x12, 0x89, 0xfc, 0xf1, + 0xad, 0x6b, 0xcb, 0x16, 0x86, 0x4e, 0xaa, 0xc6, 0x2e, 0x48, 0xed, 0x21, + 0xfc, 0x2b, 0xb0, 0x8a, 0x78, 0xb4, 0x4c, 0xb4, 0xfe, 0xf2, 0xbf, 0xdf, + 0x64, 0x2b, 0x4f, 0xff, 0x3c, 0xb9, 0xdf, 0xab, 0xd7, 0xc3, 0x30, 0x15, + 0x10, 0x64, 0xff, 0xef, 0xe3, 0xaa, 0x10, 0xd9, 0x77, 0xeb, 0x4b, 0x43, + 0x22, 0xa3, 0xc5, 0xc8, 0xda, 0x3f, 0xf5, 0x0d, 0xc9, 0xb7, 0xe2, 0xd3, + 0xdf, 0x2e, 0x3a, 0xeb, 0x41, 0x1b, 0xdb, 0x8b, 0xcf, 0xee, 0xaa, 0xbf, + 0x55, 0x7d, 0x96, 0x87, 0xa7, 0xb4, 0x51, 0x8f, 0x5d, 0x97, 0x44, 0x13, + 0xff, 0xcc, 0x36, 0x74, 0x70, 0x86, 0xb9, 0xa1, 0xf6, 0xb4, 0xe6, 0xfb, + 0x8b, 0x43, 0x2f, 0x8a, 0x72, 0x75, 0x51, 0xdb, 0x02, 0x11, 0x47, 0xf3, + 0x92, 0x8e, 0x3c, 0x43, 0xea, 0x52, 0x9f, 0x61, 0xb2, 0xae, 0xb4, 0xff, + 0xf0, 0x35, 0xee, 0xc6, 0xad, 0x15, 0xf7, 0x8b, 0x4f, 0xe1, 0x16, 0x79, + 0x98, 0x96, 0x9f, 0xda, 0x27, 0x45, 0xa7, 0xb2, 0x52, 0x32, 0xd3, 0xf5, + 0x0f, 0xbf, 0xb1, 0xc8, 0xf0, 0xfd, 0x19, 0xc5, 0x26, 0x08, 0x49, 0x97, + 0x72, 0x9e, 0xff, 0x96, 0xbd, 0x69, 0xfc, 0x2f, 0x1a, 0x33, 0x02, 0xd3, + 0x8d, 0xcd, 0x2d, 0x0c, 0x7d, 0xf4, 0x49, 0x85, 0xf3, 0xb4, 0x56, 0x2d, + 0x3f, 0xef, 0x35, 0x7f, 0x5f, 0xec, 0xc5, 0x75, 0xa7, 0xf5, 0xda, 0xca, + 0x12, 0xf6, 0xb4, 0xff, 0xcc, 0x39, 0xb6, 0xec, 0xff, 0xbd, 0xd2, 0x8e, + 0x51, 0x73, 0x48, 0x66, 0x33, 0x9f, 0x6c, 0x8a, 0xdb, 0xad, 0x3f, 0xfe, + 0xae, 0x7a, 0x61, 0x55, 0xda, 0xca, 0x12, 0xf6, 0xb4, 0x25, 0x3f, 0x5f, + 0xd3, 0x7d, 0x8c, 0x94, 0x25, 0x09, 0x42, 0x50, 0x94, 0x3c, 0xf8, 0x08, + 0x2b, 0xb2, 0xef, 0x02, 0xba, 0x82, 0x9d, 0x82, 0xa6, 0xdd, 0x25, 0x3f, + 0x66, 0x69, 0xc6, 0x32, 0x5d, 0x0b, 0x59, 0x3b, 0x89, 0x42, 0x50, 0x94, + 0x3c, 0xb4, 0x20, 0xa8, 0x4a, 0x12, 0x84, 0xa1, 0x28, 0x4a, 0x12, 0x8b, + 0x0d, 0xe7, 0x21, 0x44, 0x15, 0xd8, 0x55, 0xc2, 0x9d, 0x05, 0x42, 0x50, + 0x94, 0x3c, 0xb4, 0xb8, 0x54, 0x25, 0x09, 0x42, 0x50, 0x94, 0x3c, 0xd4, + 0x76, 0x15, 0xa0, 0xa7, 0x60, 0xa8, 0x4a, 0x12, 0x84, 0xa1, 0x28, 0xb0, + 0xd4, 0x7b, 0x0a, 0xf8, 0x56, 0xc2, 0xa5, 0xed, 0x28, 0x4a, 0x12, 0x84, + 0xa1, 0x28, 0xe4, 0xd4, 0x5a, 0x15, 0xd8, 0x57, 0x81, 0x50, 0x94, 0x25, + 0x09, 0x4f, 0xb6, 0xdd, 0xde, 0x92, 0x84, 0xa1, 0xe7, 0x9e, 0x01, 0x5b, + 0x0a, 0xc0, 0xae, 0xc9, 0xe4, 0x09, 0x42, 0x50, 0x94, 0x25, 0x09, 0x43, + 0xcd, 0x45, 0xa1, 0x44, 0x14, 0xe8, 0x2a, 0x12, 0x84, 0xa1, 0x28, 0x4a, + 0x1e, 0x6a, 0x39, 0x0a, 0xd8, 0x50, 0x85, 0x4b, 0x69, 0x42, 0x50, 0x94, + 0x9e, 0x94, 0x25, 0x69, 0x61, 0x09, 0x42, 0x50, 0x94, 0x25, 0x16, 0x1f, + 0x33, 0xc2, 0xbd, 0x8d, 0x00, 0xd3, 0x81, 0x5d, 0x85, 0x68, 0x2a, 0x54, + 0x94, 0x25, 0x09, 0x49, 0xe9, 0x42, 0x56, 0x96, 0x10, 0x94, 0x25, 0x0c, + 0x7a, 0x4f, 0x0a, 0x21, 0xaf, 0x8d, 0x18, 0x2a, 0x12, 0x84, 0xa1, 0x28, + 0x4a, 0x12, 0x86, 0x36, 0x56, 0x85, 0x7c, 0x28, 0xc1, 0x42, 0x15, 0x09, + 0x42, 0x50, 0x94, 0x7c, 0xbe, 0xb8, 0x56, 0x82, 0xa1, 0x28, 0x4a, 0x12, + 0x83, 0x17, 0xc2, 0x15, 0xa0, 0xa9, 0x19, 0x28, 0x4a, 0x12, 0x8e, 0xcb, + 0x4f, 0x02, 0xa1, 0x28, 0x4a, 0x12, 0x84, 0xa1, 0x8d, 0x43, 0x81, 0x5b, + 0x0a, 0xf0, 0x2a, 0x19, 0x7e, 0xc6, 0xc7, 0x27, 0x9e, 0xf2, 0x53, 0x4b, + 0x60, 0xdb, 0x6a, 0x41, 0x33, 0xf5, 0xcf, 0x9c, 0x3a, 0xfc, 0x23, 0x8c, + 0x91, 0xb3, 0x7c, 0x65, 0xec, 0xec, 0x5d, 0xae, 0xcf, 0xa6, 0x1f, 0x1e, + 0x5d, 0x32, 0xf0, 0x97, 0xd4, 0x59, 0xe8, 0x91, 0xd9, 0x2a, 0x7c, 0xf1, + 0x6a, 0xba, 0x47, 0x4d, 0x62, 0x71, 0x31, 0x92, 0x9e, 0x20, 0xcf, 0xad, + 0x38, 0xb9, 0xa5, 0xa7, 0x37, 0xa3, 0xda, 0x88, 0xcf, 0x9c, 0x6c, 0x6b, + 0x43, 0xf3, 0xfb, 0x65, 0xc7, 0x3f, 0x6b, 0x16, 0x8b, 0x51, 0x0c, 0xe2, + 0x8c, 0xdd, 0xb2, 0xd3, 0xf7, 0xf0, 0x7d, 0x37, 0x6b, 0x4d, 0x9f, 0x5a, + 0x44, 0xb0, 0x16, 0xb2, 0x05, 0xa4, 0x65, 0xa6, 0xea, 0x39, 0x22, 0x57, + 0xe2, 0xdb, 0x43, 0xc1, 0xdf, 0x41, 0xf3, 0xfd, 0xb6, 0x35, 0x38, 0xc3, + 0x62, 0xd1, 0x48, 0x91, 0xed, 0x66, 0x7e, 0x31, 0x75, 0x60, 0xf6, 0xb4, + 0xff, 0xf3, 0x74, 0xcf, 0xff, 0x3b, 0x63, 0xf1, 0xc7, 0x0b, 0x43, 0x22, + 0x0f, 0xc2, 0xf8, 0xb1, 0xb0, 0x04, 0x7c, 0x65, 0x3c, 0xc2, 0x78, 0x0b, + 0x0a, 0x1a, 0xae, 0x18, 0x18, 0x9f, 0x29, 0x5a, 0x23, 0x1a, 0x5e, 0xa1, + 0x4d, 0x3f, 0x98, 0x75, 0x83, 0xe5, 0x2d, 0x3f, 0x3c, 0x49, 0xfb, 0xa5, + 0xa7, 0xd6, 0x17, 0xd9, 0xeb, 0x47, 0xcf, 0x48, 0x4a, 0xe7, 0xfd, 0xb6, + 0xff, 0x63, 0x5c, 0x67, 0x6b, 0x4e, 0xaa, 0x71, 0x69, 0x56, 0xcf, 0x6b, + 0xb3, 0xf9, 0xfb, 0xcf, 0xf8, 0x6c, 0x15, 0xa7, 0x8c, 0xd5, 0x62, 0xd3, + 0xea, 0x74, 0x2d, 0x6a, 0xd0, 0x47, 0x93, 0x72, 0x19, 0xe6, 0x1d, 0x02, + 0xd2, 0x6a, 0x4d, 0x68, 0x5e, 0xee, 0x51, 0xa7, 0x7e, 0xa2, 0x19, 0xef, + 0x33, 0xef, 0x5a, 0x79, 0xbc, 0x77, 0x2e, 0x94, 0xf9, 0xe7, 0xe3, 0x8e, + 0x16, 0x81, 0x3d, 0x2f, 0x09, 0xe3, 0x94, 0x4b, 0x53, 0xa4, 0x19, 0x57, + 0x37, 0x71, 0xee, 0x79, 0x0e, 0x79, 0xfb, 0xfe, 0x77, 0x42, 0x0b, 0x4f, + 0xf5, 0x83, 0x4f, 0xdd, 0x77, 0x75, 0xa7, 0xb9, 0xe5, 0x9d, 0x2d, 0x3f, + 0xfd, 0xb6, 0x30, 0x36, 0xab, 0xe1, 0x98, 0x0a, 0x8b, 0xe2, 0x76, 0x7e, + 0xc5, 0x45, 0xff, 0x0c, 0x88, 0x00, 0x57, 0x9f, 0xdc, 0x66, 0xae, 0xd5, + 0x62, 0xd3, 0xff, 0x3a, 0xd7, 0xb6, 0x17, 0xd6, 0xc8, 0xcb, 0x4f, 0xd5, + 0xc7, 0xad, 0xe6, 0x96, 0x9f, 0xff, 0x6b, 0xd3, 0xd9, 0xd1, 0x0f, 0x7f, + 0x26, 0x35, 0x25, 0x3d, 0xbf, 0x56, 0xe9, 0x68, 0xb1, 0x15, 0x74, 0x5e, + 0x0a, 0xf3, 0x6a, 0x96, 0x9f, 0x7c, 0xac, 0xc3, 0x2a, 0x61, 0x39, 0xed, + 0x78, 0xd8, 0xa9, 0x84, 0xe6, 0xed, 0x95, 0x40, 0x9c, 0xfe, 0x1c, 0xf7, + 0xa6, 0xff, 0x6a, 0xa0, 0x4e, 0x7f, 0x5e, 0xb6, 0x57, 0xf2, 0xc5, 0x4c, + 0x27, 0x35, 0x72, 0xa9, 0x84, 0xe6, 0xe3, 0x85, 0xcc, 0x27, 0x14, 0x9a, + 0x7d, 0xa6, 0x84, 0x5c, 0x62, 0x3b, 0xa0, 0xba, 0x41, 0xe0, 0x8e, 0x5a, + 0x4c, 0xc2, 0x63, 0x9f, 0x3c, 0x8a, 0xd4, 0xfe, 0xb8, 0x8f, 0x2e, 0x31, + 0x5a, 0x5d, 0xe1, 0xe3, 0xa9, 0x45, 0x33, 0x87, 0xb3, 0x2d, 0x3f, 0xcd, + 0xe6, 0x84, 0x9d, 0x7a, 0x32, 0xd3, 0x86, 0xaf, 0x47, 0xb1, 0xf1, 0xc8, + 0x65, 0xd4, 0x3e, 0x4e, 0x42, 0x14, 0xbb, 0x21, 0xd4, 0xb7, 0xe7, 0x50, + 0x95, 0x9f, 0x73, 0x5f, 0x2f, 0x6b, 0x4f, 0x86, 0xbd, 0x53, 0x8b, 0x4f, + 0xf6, 0xf0, 0xdb, 0x26, 0xb5, 0xeb, 0x4f, 0xde, 0x85, 0xfd, 0x59, 0x62, + 0xd0, 0x47, 0xd5, 0xd9, 0xc4, 0x0a, 0x2d, 0x35, 0x09, 0x29, 0xff, 0x56, + 0x6d, 0xc2, 0x1d, 0xd5, 0xab, 0x43, 0x2f, 0x8e, 0xd4, 0xeb, 0x81, 0x36, + 0x64, 0x37, 0x44, 0x9e, 0x7f, 0xf1, 0xb5, 0x72, 0x1b, 0x5f, 0xa2, 0xb9, + 0x2d, 0x3f, 0xff, 0x86, 0xad, 0xab, 0xe0, 0xec, 0x9b, 0x5b, 0xf3, 0x0c, + 0xb4, 0xfc, 0x3e, 0x18, 0xb6, 0xcb, 0x4f, 0xff, 0xb0, 0x75, 0x99, 0xb1, + 0x6d, 0x5f, 0x8a, 0xda, 0xd3, 0xfe, 0xb3, 0x06, 0xfa, 0xd9, 0x35, 0xd6, + 0x9d, 0xfb, 0xdd, 0x71, 0x01, 0xcf, 0xfe, 0xfb, 0x6d, 0xba, 0x57, 0xc3, + 0x30, 0x15, 0x10, 0x19, 0xcd, 0x4c, 0x62, 0x32, 0xbd, 0x33, 0x47, 0x69, + 0xa0, 0x6a, 0x31, 0xc8, 0xa4, 0xe5, 0xca, 0x36, 0xc9, 0xe1, 0xd7, 0x7e, + 0x2d, 0x3f, 0xff, 0x3e, 0xae, 0x5f, 0xf9, 0x1b, 0xd6, 0xb7, 0x5c, 0x69, + 0x68, 0xa4, 0x40, 0x61, 0x1c, 0xff, 0xff, 0x63, 0xe8, 0x5c, 0x7d, 0x5a, + 0xff, 0x4d, 0xd9, 0xf8, 0xe3, 0x84, 0xa3, 0x68, 0x8e, 0x12, 0x19, 0xfc, + 0xd5, 0xf0, 0xcc, 0x05, 0x44, 0x13, 0x3f, 0xcd, 0xaa, 0xf8, 0x66, 0x02, + 0xa2, 0xf9, 0x9f, 0x13, 0xa1, 0xab, 0xf2, 0x7f, 0x80, 0x77, 0x3f, 0xbc, + 0xdf, 0x56, 0xc8, 0x36, 0xb4, 0xff, 0xac, 0xcb, 0x7a, 0xab, 0x43, 0x8e, + 0x96, 0x9d, 0xc7, 0x1c, 0x25, 0x3e, 0xdd, 0x06, 0x7d, 0x23, 0x97, 0xf3, + 0xff, 0xf9, 0xcf, 0xb3, 0xae, 0x9e, 0xf3, 0xa7, 0xa7, 0x2f, 0xd2, 0xad, + 0xd2, 0xd1, 0xa4, 0x52, 0x7a, 0x34, 0x8b, 0x13, 0x2b, 0x18, 0xc1, 0xa7, + 0xfe, 0xb0, 0xcd, 0x6d, 0xc6, 0xac, 0xf4, 0xf5, 0xa7, 0xff, 0xbd, 0x5a, + 0x3d, 0x03, 0x65, 0xdf, 0x6d, 0xf7, 0xad, 0x3f, 0xef, 0x2e, 0xd4, 0x3a, + 0x77, 0xf8, 0x05, 0xa7, 0x71, 0xc7, 0x09, 0x4f, 0xef, 0x5d, 0xb0, 0xd5, + 0xba, 0x48, 0xe5, 0xfc, 0xff, 0xfc, 0xee, 0x74, 0x0d, 0x97, 0x3c, 0xd7, + 0x1d, 0x35, 0x7a, 0xb1, 0x69, 0x66, 0xd1, 0x57, 0xe2, 0x24, 0x3d, 0x5c, + 0xef, 0x27, 0xe5, 0x1b, 0x0f, 0xca, 0x8c, 0x90, 0x2a, 0xba, 0x8c, 0x36, + 0x7d, 0xba, 0xd3, 0x8f, 0x5a, 0x7f, 0xd5, 0xa6, 0xfd, 0xf6, 0xc3, 0xa5, + 0xc4, 0x11, 0x3f, 0x9a, 0xbe, 0x19, 0x80, 0xa8, 0x82, 0x0e, 0x79, 0x33, + 0xf6, 0x6f, 0xff, 0x2e, 0x16, 0x9f, 0xba, 0xfc, 0xf1, 0x82, 0xf5, 0xa0, + 0x4f, 0x7f, 0xc2, 0xd8, 0xda, 0x67, 0xdd, 0xb8, 0x8c, 0x2a, 0xe7, 0xf9, + 0x87, 0x5e, 0xab, 0x79, 0x6a, 0xd3, 0xff, 0xd9, 0xc6, 0xab, 0x6c, 0x5a, + 0x1a, 0xd9, 0x2d, 0x0f, 0x44, 0x28, 0x9c, 0xcf, 0xf6, 0xdb, 0xfa, 0x16, + 0xab, 0x56, 0x9f, 0xff, 0xe2, 0xb1, 0x9f, 0x7f, 0xfc, 0xad, 0x71, 0xf9, + 0xf3, 0x55, 0xab, 0x4f, 0x6b, 0x74, 0x3c, 0xa2, 0x83, 0x66, 0xf3, 0xf7, + 0xa3, 0x5f, 0x8c, 0xb5, 0x68, 0x63, 0xeb, 0xd1, 0xd4, 0xf1, 0x38, 0x5c, + 0x2d, 0x3f, 0xfe, 0xf2, 0xc1, 0x6a, 0xd9, 0xdb, 0x55, 0xbf, 0x3e, 0xb4, + 0xfa, 0xb5, 0x7f, 0x57, 0xe4, 0xfe, 0x3d, 0x11, 0x4f, 0xc1, 0xb2, 0xea, + 0x2f, 0x6b, 0x4f, 0xc6, 0x6e, 0xbe, 0xea, 0xc5, 0xa7, 0xff, 0xff, 0x8b, + 0x58, 0x6c, 0x1e, 0xde, 0x57, 0xf0, 0xdb, 0x26, 0xd6, 0xfc, 0xc3, 0x2d, + 0x1c, 0xa3, 0x78, 0x8c, 0x30, 0xc6, 0x7e, 0x1e, 0xe8, 0xcd, 0xb5, 0xa7, + 0x7f, 0xd5, 0xd6, 0x9f, 0xf6, 0x08, 0x57, 0xc3, 0x30, 0x15, 0x10, 0x8c, + 0x31, 0xf1, 0xf8, 0x3d, 0x3f, 0xf9, 0xaa, 0xdf, 0x5a, 0x21, 0xf1, 0xf5, + 0x75, 0xa7, 0xff, 0xb3, 0x2c, 0xf5, 0x5b, 0xc3, 0x1f, 0x8e, 0x38, 0x5a, + 0x39, 0x44, 0xfb, 0x89, 0x73, 0xfd, 0xcb, 0x5e, 0xed, 0x65, 0x70, 0xb4, + 0x51, 0xef, 0xe1, 0x2c, 0xee, 0x38, 0xe1, 0x29, 0xfe, 0xae, 0xf3, 0xf4, + 0xea, 0xb9, 0x48, 0xe5, 0xfc, 0xdc, 0x70, 0x94, 0xee, 0x38, 0xe1, 0x29, + 0xfb, 0x2c, 0xe7, 0x6d, 0x74, 0x8e, 0x5f, 0xc0, 0xa2, 0xf7, 0x84, 0x9e, + 0xa3, 0x79, 0xf0, 0x17, 0x3e, 0x8c, 0x91, 0xcd, 0x9c, 0xee, 0x38, 0xe1, + 0x29, 0xd7, 0x6f, 0xa4, 0x72, 0xfe, 0x5d, 0x92, 0x20, 0xb4, 0xb1, 0x3f, + 0x72, 0x2c, 0xfc, 0x05, 0xa7, 0xf7, 0xaf, 0xf2, 0x4e, 0x9b, 0x95, 0xa7, + 0xfe, 0xde, 0x3c, 0x73, 0xdb, 0x82, 0x4e, 0x2d, 0x3f, 0x6e, 0x9d, 0x56, + 0xae, 0xb4, 0x01, 0xf9, 0xe9, 0x16, 0x3e, 0x8f, 0x7d, 0x95, 0x8c, 0x2a, + 0xe1, 0x93, 0x54, 0xa8, 0xc8, 0x27, 0x5b, 0xd6, 0xbb, 0xba, 0x5a, 0x7f, + 0xf5, 0x75, 0xf0, 0x7b, 0xa0, 0x6d, 0xb1, 0x96, 0x9f, 0x80, 0xaf, 0xb2, + 0x71, 0x29, 0xfc, 0x35, 0x6b, 0xee, 0x5e, 0xd6, 0x9e, 0xcc, 0xff, 0xb5, + 0xa3, 0xa1, 0xeb, 0x58, 0x69, 0x3c, 0xd8, 0x67, 0x49, 0x4e, 0xe3, 0x8e, + 0x12, 0x9f, 0xfe, 0xf4, 0xdd, 0xd5, 0x0e, 0xb6, 0x4c, 0x36, 0x24, 0x72, + 0xfe, 0x54, 0x08, 0x9f, 0x32, 0x0c, 0x32, 0x7c, 0x6f, 0x2c, 0xb5, 0x28, + 0xa1, 0x05, 0xb8, 0x62, 0x4f, 0xff, 0x8d, 0x40, 0xc3, 0x9a, 0xbf, 0x3e, + 0x67, 0xde, 0xb4, 0xf9, 0xb5, 0x77, 0x54, 0xb4, 0x31, 0xfe, 0x69, 0x52, + 0x7f, 0xf8, 0x9d, 0x50, 0xf2, 0x39, 0xc5, 0x0e, 0x7b, 0x5a, 0x7f, 0xff, + 0xb9, 0xd9, 0x71, 0x4e, 0xc4, 0x6c, 0xd5, 0xfc, 0x7d, 0x5b, 0xa5, 0xa2, + 0x91, 0x79, 0x8a, 0x10, 0xcd, 0xad, 0xed, 0x89, 0x2f, 0x8f, 0xd7, 0x98, + 0xcd, 0xaa, 0x70, 0xec, 0xa3, 0xaf, 0x72, 0x17, 0x7f, 0x8c, 0xb4, 0xd0, + 0x99, 0xdc, 0x64, 0x58, 0x5f, 0xdc, 0x23, 0xc6, 0x32, 0x0b, 0xcb, 0x05, + 0xd4, 0xa0, 0xbf, 0x21, 0xa1, 0xc4, 0x37, 0x67, 0x3a, 0x61, 0x5a, 0x7f, + 0xfa, 0x84, 0xfa, 0xf6, 0x56, 0xdf, 0x75, 0xde, 0x2d, 0x2b, 0x5e, 0x7d, + 0xbc, 0x8e, 0x4f, 0xdb, 0x70, 0xb6, 0x46, 0x5a, 0x7f, 0xc2, 0xda, 0xde, + 0x77, 0x96, 0xdd, 0x69, 0xce, 0x79, 0xf5, 0xa7, 0xfd, 0x85, 0xfa, 0xb4, + 0xfc, 0x71, 0xc2, 0xd1, 0x87, 0xbf, 0x71, 0xe9, 0xff, 0xe1, 0x67, 0xf4, + 0xf5, 0xa2, 0x1f, 0x1f, 0x57, 0x5a, 0x29, 0x33, 0xd0, 0x2d, 0xdc, 0x27, + 0x7b, 0x21, 0x9f, 0xcc, 0x2f, 0x1a, 0xae, 0xd6, 0x9f, 0xcf, 0xaf, 0xdc, + 0x5a, 0xc5, 0xa7, 0xff, 0xab, 0x4c, 0x21, 0x5a, 0xd9, 0x7f, 0xb0, 0x5a, + 0x7f, 0x31, 0xaf, 0x7c, 0x1b, 0x16, 0x9f, 0x65, 0xe8, 0x74, 0xb4, 0xed, + 0x67, 0x5d, 0x69, 0xfd, 0xad, 0x91, 0xfb, 0xc2, 0x5a, 0x39, 0x47, 0xa6, + 0xd3, 0x04, 0xcb, 0x44, 0xbe, 0x0f, 0xcf, 0xef, 0x3b, 0x6d, 0x96, 0x3d, + 0x69, 0xfe, 0x0a, 0xd3, 0x3a, 0x21, 0xed, 0x69, 0xff, 0xfb, 0xc6, 0xd5, + 0xe8, 0x7a, 0x7d, 0x8b, 0x91, 0xc7, 0xad, 0x04, 0x89, 0x31, 0x38, 0x9f, + 0xff, 0x86, 0xaf, 0xe7, 0x4a, 0xde, 0x0d, 0x38, 0xf6, 0xb5, 0x69, 0xff, + 0x55, 0xfc, 0xaf, 0x86, 0x60, 0x2a, 0x20, 0x69, 0xed, 0x6f, 0x1f, 0xd1, + 0x14, 0x82, 0xb9, 0x0c, 0x98, 0x05, 0x43, 0x16, 0x7f, 0xd9, 0xfa, 0x1e, + 0xef, 0xab, 0xda, 0xb4, 0xff, 0xff, 0xfd, 0x5a, 0xde, 0x0f, 0xbe, 0x97, + 0xfe, 0x66, 0x9d, 0x57, 0x3d, 0x28, 0xd8, 0x36, 0xbd, 0x71, 0x05, 0xcf, + 0xfb, 0x33, 0xd8, 0x67, 0x3d, 0x3d, 0xf0, 0xb8, 0x82, 0xe7, 0xfe, 0xd9, + 0x6c, 0x98, 0x75, 0xd3, 0xdf, 0x0b, 0x88, 0x2e, 0x7f, 0x31, 0x0e, 0xba, + 0x7b, 0xe1, 0x71, 0x05, 0xcf, 0xc6, 0xae, 0x7a, 0x7b, 0xe1, 0x71, 0x05, + 0xcf, 0xff, 0xf6, 0x08, 0x91, 0xba, 0x5c, 0x36, 0x5f, 0x2f, 0x76, 0x57, + 0x0b, 0x88, 0x2e, 0x6b, 0x7a, 0x72, 0x9c, 0xe8, 0x28, 0xfd, 0x53, 0x10, + 0xc5, 0x02, 0x19, 0x56, 0x86, 0xcf, 0xc6, 0x51, 0xcc, 0xfe, 0x26, 0xf7, + 0x7d, 0x5e, 0xd5, 0xa7, 0xb3, 0xfd, 0xe2, 0xd3, 0xff, 0x6c, 0xb6, 0x4c, + 0x3a, 0xe9, 0xef, 0x85, 0xc4, 0x17, 0x3f, 0xce, 0x5c, 0x0a, 0xce, 0x9e, + 0xf8, 0x5c, 0x41, 0x73, 0xed, 0x5d, 0x8d, 0xd0, 0x11, 0x41, 0xe9, 0x52, + 0x7f, 0xf7, 0x40, 0xd9, 0x03, 0x6a, 0xfd, 0x3d, 0xf0, 0xb8, 0x82, 0xe7, + 0xff, 0xfe, 0x11, 0x23, 0x74, 0xf2, 0xba, 0x5c, 0x36, 0x5f, 0x2f, 0x76, + 0x57, 0x0b, 0x88, 0x2e, 0x29, 0x32, 0x3b, 0x50, 0xf1, 0x72, 0x7f, 0xb6, + 0x5f, 0x2f, 0x76, 0x57, 0x0b, 0x88, 0x2e, 0x7f, 0xfb, 0x32, 0xd7, 0xdf, + 0x65, 0xcf, 0x2d, 0xf6, 0x4a, 0x7f, 0xd4, 0xf7, 0xf9, 0x7f, 0x8d, 0x9d, + 0x4b, 0x88, 0x2e, 0x01, 0x1d, 0x1f, 0x48, 0xba, 0x84, 0xff, 0x80, 0xbf, + 0xac, 0xee, 0xfd, 0x38, 0x5c, 0x41, 0x73, 0xf6, 0xcb, 0x7b, 0x2e, 0xd5, + 0x00, 0x5c, 0xfa, 0xbb, 0xe9, 0xef, 0x85, 0xc4, 0x17, 0x35, 0x68, 0x0f, + 0xd3, 0x67, 0x51, 0x6a, 0x3b, 0xaf, 0x0c, 0x29, 0xf8, 0xd5, 0xcf, 0x4f, + 0x7c, 0x2e, 0x20, 0xb9, 0xff, 0x06, 0xcb, 0xe5, 0xee, 0xca, 0xe1, 0x71, + 0x05, 0xcd, 0x5d, 0x31, 0x11, 0xb7, 0x40, 0x9f, 0xde, 0x11, 0xb0, 0x6d, + 0x7a, 0xe2, 0x0b, 0x9f, 0xf5, 0x13, 0xaa, 0x1a, 0xe7, 0x1e, 0xb8, 0x82, + 0xcc, 0x78, 0x11, 0xca, 0xf0, 0x2f, 0xcd, 0xfb, 0x35, 0x18, 0xf9, 0x2f, + 0x18, 0xc6, 0xa3, 0x1d, 0xf2, 0x16, 0xdc, 0x37, 0xcf, 0xbb, 0xbf, 0x7d, + 0xb2, 0xa2, 0x0b, 0x3a, 0x23, 0xa7, 0xfd, 0x4f, 0xde, 0x3d, 0xd9, 0xdb, + 0xcb, 0x16, 0x9c, 0x66, 0x7a, 0xd3, 0xea, 0xe7, 0x7e, 0x70, 0xb4, 0xbf, + 0x87, 0x8a, 0x23, 0x73, 0x8b, 0xaa, 0x96, 0x9d, 0x9f, 0xed, 0x69, 0x5a, + 0xc6, 0xe7, 0x43, 0xb3, 0xf5, 0x59, 0x9b, 0x6e, 0xba, 0xd0, 0x48, 0xb6, + 0xc5, 0xf1, 0x27, 0x9d, 0x9f, 0xb1, 0x69, 0xbb, 0x65, 0xa7, 0x89, 0x8d, + 0x4b, 0x42, 0xd3, 0xf6, 0x7b, 0xd3, 0x7f, 0xb5, 0xa3, 0x93, 0x72, 0x21, + 0x53, 0xff, 0xf9, 0x8b, 0x91, 0x6f, 0x03, 0x54, 0x1c, 0xb0, 0x7a, 0x32, + 0xd3, 0x76, 0xcb, 0x4c, 0xde, 0xd6, 0x9f, 0xea, 0xd5, 0xd8, 0xde, 0xa9, + 0xc5, 0xa7, 0xf5, 0xeb, 0x65, 0x7f, 0x2c, 0x5a, 0x6e, 0x38, 0x4a, 0x7f, + 0x86, 0x9d, 0x63, 0xee, 0x5c, 0xad, 0x00, 0x9f, 0xb9, 0x0e, 0x7c, 0x58, + 0xcb, 0x1b, 0x21, 0xed, 0x81, 0xdc, 0x16, 0x11, 0x7b, 0x9d, 0x70, 0x69, + 0xe8, 0x62, 0x77, 0x1c, 0x70, 0x94, 0x8c, 0x91, 0xcb, 0xf9, 0xf6, 0x39, + 0x99, 0xf4, 0x8e, 0x8d, 0xdf, 0x50, 0xbe, 0x9f, 0xd6, 0xe9, 0xab, 0x75, + 0x62, 0xd0, 0xcd, 0x9d, 0x25, 0x46, 0xcf, 0xed, 0x0a, 0xd3, 0x02, 0x8c, + 0x9b, 0xe9, 0x7b, 0x8f, 0x1b, 0x29, 0x31, 0x42, 0x93, 0x78, 0xd0, 0x7c, + 0x96, 0x02, 0xe9, 0x32, 0x7a, 0x81, 0xb4, 0xb4, 0xf5, 0x1a, 0xb4, 0xb4, + 0xff, 0xdb, 0xf2, 0xcf, 0x0f, 0xb2, 0x0c, 0xfa, 0xd3, 0xd9, 0x67, 0xa7, + 0xad, 0x0c, 0x8a, 0x9b, 0x47, 0xf4, 0x40, 0xec, 0x8d, 0x3f, 0x0f, 0x9c, + 0x9b, 0x1e, 0xb4, 0xff, 0xf5, 0xaf, 0x16, 0xe8, 0x61, 0x6f, 0x7a, 0x2b, + 0x16, 0x9f, 0xd7, 0xd3, 0xaa, 0x1a, 0xe5, 0x68, 0x64, 0x5a, 0x91, 0x76, + 0x29, 0xce, 0xce, 0x9e, 0x96, 0x9f, 0xfe, 0x17, 0xf4, 0xae, 0x4a, 0xf6, + 0xeb, 0xcc, 0xba, 0xd3, 0xee, 0x9b, 0x6f, 0xbd, 0x68, 0xe8, 0x89, 0xba, + 0x1f, 0xe1, 0x4e, 0x7e, 0xb1, 0xc7, 0xf5, 0x9f, 0xb1, 0x69, 0x9f, 0x62, + 0xd3, 0xed, 0xd1, 0x3e, 0xeb, 0x4f, 0xff, 0x6d, 0xbd, 0x1f, 0x43, 0x9d, + 0xde, 0xed, 0xda, 0x53, 0xfb, 0xba, 0xf8, 0x66, 0x02, 0xe2, 0x04, 0x9d, + 0xa2, 0xb1, 0x68, 0x7a, 0x34, 0x79, 0x26, 0xfa, 0x91, 0x8f, 0x66, 0x76, + 0x7a, 0xd3, 0xda, 0xb3, 0x05, 0x69, 0xeb, 0x6f, 0x9a, 0x5a, 0x2c, 0x3d, + 0xca, 0x19, 0xd9, 0x0c, 0xfe, 0x1c, 0xe2, 0xf7, 0x6e, 0xd6, 0x9d, 0xc7, + 0x1c, 0x2e, 0xaf, 0xa9, 0xd8, 0x3c, 0xa6, 0xaf, 0xa1, 0xcd, 0x64, 0x72, + 0x89, 0x8e, 0xd7, 0xe7, 0xff, 0xd4, 0x25, 0xec, 0xf7, 0xd6, 0xfc, 0xc7, + 0xbd, 0x96, 0x8b, 0x0f, 0xef, 0xd9, 0x2c, 0xfb, 0x04, 0x48, 0xcb, 0x47, + 0x5b, 0x56, 0x86, 0xf3, 0x6a, 0x87, 0x41, 0x42, 0x6b, 0x23, 0x42, 0x12, + 0x59, 0xf1, 0x69, 0xb5, 0x74, 0xa7, 0x81, 0xb5, 0x74, 0xa6, 0xe3, 0x84, + 0xa1, 0xe7, 0xbd, 0x44, 0xdc, 0x10, 0x4d, 0x5c, 0x24, 0x73, 0x5f, 0x3f, + 0xfe, 0xad, 0x30, 0x55, 0x0e, 0xb6, 0x4c, 0x36, 0x2d, 0x1d, 0x9f, 0xb7, + 0x04, 0xd3, 0xff, 0xf9, 0x9d, 0x10, 0xf7, 0xd3, 0x57, 0xa0, 0xde, 0x0e, + 0xae, 0xb4, 0xfd, 0x6b, 0xf7, 0xe3, 0x7d, 0x69, 0xff, 0x55, 0x39, 0xfa, + 0xf0, 0xcd, 0x75, 0xa1, 0xc3, 0xed, 0xf9, 0x7c, 0xe7, 0xe7, 0xd6, 0x9f, + 0x3e, 0xb5, 0x5c, 0xa5, 0x22, 0x70, 0xf0, 0xb4, 0x37, 0x3d, 0xaf, 0x75, + 0xb5, 0xa6, 0xed, 0x96, 0x9b, 0xb6, 0x5a, 0x7d, 0xe3, 0xe8, 0x4e, 0x46, + 0xb3, 0xb1, 0x68, 0x64, 0x46, 0x8a, 0x7c, 0xff, 0xda, 0xdd, 0x1b, 0xd3, + 0x77, 0x56, 0xe9, 0x69, 0xfd, 0x68, 0x17, 0xfd, 0x37, 0x2b, 0x4f, 0x76, + 0x6c, 0x7d, 0xcf, 0xf3, 0x48, 0xf3, 0xba, 0xaa, 0xd5, 0xa7, 0xbb, 0xf9, + 0x7d, 0x68, 0x63, 0xfb, 0xc3, 0xae, 0x07, 0xe7, 0xaf, 0xe5, 0xba, 0x5a, + 0x77, 0x1c, 0x70, 0x94, 0xfa, 0xbd, 0x8f, 0x97, 0x48, 0xe5, 0xfc, 0xfa, + 0x8f, 0xc7, 0x1c, 0x2d, 0x0c, 0x7c, 0x5a, 0x38, 0x9f, 0xfa, 0x86, 0xae, + 0x1b, 0x20, 0x61, 0x5a, 0x7b, 0x8c, 0x17, 0xad, 0x3f, 0xda, 0x6b, 0x7b, + 0xcd, 0xec, 0x96, 0x96, 0xd6, 0x8a, 0x3c, 0x90, 0x39, 0x9d, 0xc7, 0x1c, + 0x25, 0x3f, 0x16, 0x7b, 0xd9, 0x69, 0x23, 0x97, 0xf3, 0xea, 0xee, 0xa9, + 0xc5, 0xa5, 0x7e, 0x88, 0xa2, 0xf9, 0xf8, 0x9e, 0x4d, 0xe3, 0xf9, 0x4d, + 0x0e, 0xa3, 0x0c, 0x91, 0x6d, 0x3b, 0x81, 0x8e, 0x06, 0x19, 0x77, 0xfd, + 0xe4, 0x95, 0x0c, 0xff, 0x6c, 0xbf, 0x85, 0xae, 0xe3, 0x18, 0xc2, 0xeb, + 0xc2, 0x97, 0x51, 0xec, 0xcf, 0xcc, 0x6f, 0xff, 0x34, 0xb4, 0xff, 0xf1, + 0x1a, 0xd7, 0xdf, 0xa5, 0x08, 0xd1, 0x76, 0xb4, 0x6c, 0xff, 0x34, 0x59, + 0x23, 0xbb, 0xd0, 0x9f, 0xd7, 0x77, 0x65, 0x3d, 0x6a, 0x41, 0xeb, 0x42, + 0xa6, 0x9c, 0xaa, 0xb2, 0x50, 0x2b, 0xe5, 0x55, 0xf3, 0x2e, 0x6a, 0xab, + 0x90, 0x1f, 0x71, 0xdb, 0x84, 0xad, 0xdb, 0x65, 0xa9, 0x14, 0xad, 0xc7, + 0x27, 0xd2, 0xbf, 0x3b, 0x78, 0x69, 0x5e, 0x5b, 0xa4, 0x2f, 0x65, 0x61, + 0x17, 0xdc, 0xb9, 0x91, 0x9f, 0x5c, 0xbd, 0x6c, 0x25, 0xaa, 0xd5, 0x43, + 0xc8, 0xdf, 0x1d, 0x43, 0xd7, 0x88, 0x64, 0x75, 0x4b, 0x75, 0xf5, 0x3e, + 0xda, 0xed, 0x18, 0xbc, 0x1e, 0x14, 0x59, 0x0f, 0xc5, 0x03, 0x54, 0xfe, + 0x3d, 0x7c, 0x33, 0x01, 0x51, 0x71, 0xcf, 0xe3, 0xd7, 0xc3, 0x30, 0x15, + 0x17, 0x5c, 0xff, 0xc7, 0xc7, 0x9e, 0xbe, 0x19, 0x80, 0xa8, 0x94, 0x61, + 0xa1, 0x4c, 0x4e, 0xf2, 0x8e, 0x4f, 0x3d, 0x9e, 0x01, 0xe1, 0x43, 0xd3, + 0xae, 0x7f, 0x98, 0xa3, 0x1b, 0xb9, 0xc6, 0x8f, 0x1d, 0x8f, 0x27, 0xff, + 0x1c, 0xd8, 0xf3, 0xd7, 0xc3, 0x30, 0x15, 0x12, 0xd4, 0xfb, 0xe1, 0x98, + 0x0a, 0x88, 0xde, 0x7f, 0xd8, 0xf3, 0xd7, 0xc3, 0x30, 0x15, 0x12, 0xfc, + 0x8f, 0x47, 0xf0, 0x63, 0x19, 0xfc, 0x7a, 0xf8, 0x66, 0x02, 0xa2, 0xab, + 0x9f, 0xef, 0x74, 0x35, 0x6e, 0xb0, 0xcb, 0x4d, 0xc9, 0x2d, 0x3f, 0x57, + 0xc3, 0x30, 0x15, 0x12, 0x04, 0x74, 0x3c, 0xc3, 0x8b, 0x4f, 0xaf, 0x83, + 0x96, 0xad, 0x0f, 0x3c, 0xab, 0x49, 0x27, 0xff, 0x53, 0x9b, 0xc3, 0x6b, + 0x6d, 0xaf, 0x0c, 0xb4, 0x7b, 0x4c, 0xf7, 0x21, 0x9f, 0xe8, 0x8e, 0x7f, + 0xe1, 0xab, 0x0f, 0xd4, 0xc2, 0x35, 0xa5, 0xa0, 0xe7, 0xfb, 0xf3, 0x99, + 0xfc, 0x7a, 0xf8, 0x66, 0x02, 0xa2, 0xc8, 0x9f, 0xc7, 0xaf, 0x86, 0x60, + 0x2a, 0x2d, 0x79, 0xfc, 0x7a, 0xf8, 0x66, 0x02, 0xa2, 0xe4, 0x9f, 0x7c, + 0x33, 0x01, 0x51, 0x76, 0x4f, 0xfb, 0x1e, 0x7a, 0xf8, 0x66, 0x02, 0xa2, + 0x8e, 0x91, 0xe8, 0xfe, 0x0c, 0x63, 0x27, 0xad, 0x3e, 0xf8, 0x66, 0x02, + 0xa2, 0x95, 0x9f, 0xff, 0xfe, 0xdb, 0x58, 0xdb, 0x27, 0x59, 0xce, 0xc8, + 0xe1, 0xb2, 0x73, 0x6d, 0x65, 0x2d, 0x33, 0xcf, 0x48, 0xb0, 0x70, 0xc6, + 0x63, 0x9a, 0xd4, 0x77, 0xe4, 0x30, 0x22, 0xc5, 0xd8, 0x07, 0xc3, 0x2e, + 0xd2, 0x72, 0x8f, 0xd8, 0xc4, 0x5d, 0x9e, 0x5c, 0xf3, 0x50, 0xb4, 0x75, + 0x18, 0xb4, 0xff, 0x3c, 0xf5, 0xf0, 0xcc, 0x05, 0x44, 0x71, 0x3f, 0xc4, + 0x7a, 0xf8, 0x66, 0x02, 0xa2, 0xb5, 0x91, 0xf1, 0x10, 0x7a, 0x42, 0x9f, + 0xfc, 0x73, 0x63, 0xcf, 0x5f, 0x0c, 0xc0, 0x54, 0x4b, 0x73, 0x55, 0xab, + 0x4f, 0xee, 0x68, 0xc6, 0x62, 0xba, 0xd1, 0x69, 0xe4, 0x10, 0xb4, 0xed, + 0xf2, 0xf5, 0xa7, 0x3c, 0xc0, 0xb4, 0xff, 0xfd, 0xbc, 0xb7, 0xbe, 0x77, + 0x8f, 0xab, 0x8f, 0x99, 0xe9, 0x68, 0x54, 0x43, 0x73, 0xfe, 0xc7, 0x9e, + 0xbe, 0x19, 0x80, 0xa8, 0x98, 0x26, 0x0a, 0x5a, 0x6f, 0x3b, 0x4a, 0x08, + 0xd6, 0x7c, 0x52, 0x7f, 0x0d, 0x6b, 0x4d, 0xfb, 0xad, 0x23, 0xb2, 0x72, + 0x96, 0x11, 0x72, 0x3b, 0x43, 0x60, 0xbe, 0x61, 0x7d, 0x39, 0xfa, 0x20, + 0x9c, 0x6f, 0x3e, 0x94, 0xff, 0xb1, 0xe7, 0xaf, 0x86, 0x60, 0x2a, 0x26, + 0x39, 0x1c, 0x8f, 0x90, 0xc3, 0xb3, 0xf3, 0x5f, 0xa6, 0xab, 0x6b, 0x4e, + 0x61, 0xb1, 0x69, 0xff, 0xff, 0xe7, 0xdf, 0x75, 0xe7, 0x17, 0xdd, 0x05, + 0x5f, 0xa5, 0x5a, 0xfb, 0x90, 0x92, 0xd3, 0xc1, 0x98, 0x0a, 0x8a, 0xc6, + 0x7f, 0xdd, 0x55, 0xa1, 0xaf, 0x18, 0x74, 0xb4, 0x7b, 0x4c, 0xc8, 0x0b, + 0xad, 0x1b, 0xfb, 0xfe, 0x8a, 0xe7, 0xff, 0x30, 0xeb, 0xdf, 0x8c, 0x34, + 0x0d, 0xf5, 0xa7, 0xfb, 0x9d, 0xd5, 0xed, 0x7b, 0x6d, 0x69, 0xfe, 0x6b, + 0x5e, 0xe3, 0xf3, 0xf6, 0x2d, 0x14, 0x7e, 0xa4, 0x75, 0x3f, 0xea, 0xe7, + 0xe5, 0xe5, 0x9d, 0xdd, 0xeb, 0x4f, 0xff, 0xfc, 0x3e, 0x59, 0x41, 0xd0, + 0x7c, 0x76, 0xe9, 0x56, 0xbe, 0xbc, 0x1e, 0xee, 0xb4, 0xfe, 0xeb, 0x76, + 0x38, 0xfe, 0xb3, 0xf6, 0x2d, 0x3f, 0xfa, 0x9c, 0xde, 0x1b, 0x5b, 0x6d, + 0x78, 0x65, 0xa7, 0x6c, 0x8f, 0x4a, 0x9d, 0x41, 0x37, 0x70, 0xbd, 0x12, + 0x0d, 0x21, 0x75, 0x3e, 0x7a, 0x42, 0x9b, 0xd7, 0x6b, 0x4d, 0xe3, 0x8b, + 0x4f, 0xb0, 0x6c, 0xf2, 0xeb, 0x47, 0x67, 0xb2, 0x23, 0x37, 0x18, 0x9f, + 0x79, 0x6d, 0x8d, 0xed, 0x69, 0xf1, 0xa8, 0x59, 0xeb, 0x4f, 0x37, 0xf0, + 0x56, 0x9e, 0xbd, 0xdb, 0xb5, 0xa1, 0x8f, 0x9b, 0x64, 0xbc, 0x0f, 0xcf, + 0x99, 0xfd, 0xf8, 0xf5, 0xa7, 0x30, 0xbd, 0x68, 0x70, 0xf0, 0xf4, 0x53, + 0x3b, 0x7e, 0x8c, 0xb4, 0xfc, 0xc6, 0xa1, 0x2f, 0x6b, 0x4a, 0xeb, 0x41, + 0x1b, 0xcc, 0x2c, 0x9b, 0xb6, 0x4a, 0x6e, 0x38, 0x4a, 0x08, 0xd7, 0x70, + 0x2d, 0x3f, 0xb1, 0xe3, 0x5a, 0xd9, 0x24, 0x73, 0x43, 0x3d, 0xce, 0x5b, + 0x75, 0xa7, 0x30, 0xb8, 0xb4, 0xc2, 0xcb, 0x43, 0x86, 0xbf, 0xe3, 0x73, + 0xff, 0x7b, 0x21, 0x0b, 0xb1, 0xb2, 0xdd, 0x2d, 0x3b, 0xba, 0x76, 0x5a, + 0x3d, 0x9f, 0x1f, 0xd1, 0x25, 0xed, 0x69, 0xbf, 0xed, 0x68, 0x23, 0x55, + 0xe8, 0x4a, 0x7f, 0xf8, 0xb4, 0xcf, 0x2d, 0x6e, 0xad, 0xd7, 0x8c, 0xb4, + 0x32, 0x72, 0xd4, 0xa4, 0x50, 0x85, 0xda, 0x76, 0x11, 0x42, 0xd2, 0x32, + 0xd2, 0xde, 0x8b, 0xa7, 0x41, 0x53, 0xf7, 0x6d, 0xba, 0x75, 0x8b, 0x4f, + 0xc5, 0xaa, 0xde, 0x7b, 0x5a, 0x77, 0x1c, 0x70, 0x94, 0xff, 0xd4, 0x1c, + 0xb5, 0x9e, 0xab, 0x79, 0x6a, 0x47, 0x2f, 0xe7, 0x8b, 0xee, 0xdc, 0xad, + 0x2f, 0xad, 0x3e, 0x31, 0x6b, 0xbc, 0x5a, 0x2c, 0x3d, 0xce, 0xb9, 0x2f, + 0x82, 0x13, 0xf8, 0x0a, 0xe3, 0x4e, 0xb1, 0x69, 0xab, 0x4b, 0x45, 0xa7, + 0x8d, 0xb3, 0x19, 0xed, 0x0d, 0x3d, 0x69, 0xff, 0xc5, 0x7d, 0xd7, 0x23, + 0x4e, 0x86, 0xae, 0xb4, 0x7c, 0xfa, 0x74, 0x41, 0x23, 0xb2, 0xf6, 0xb5, + 0x85, 0xfc, 0xc2, 0x4a, 0x9c, 0x88, 0x8f, 0xeb, 0x46, 0x6e, 0xdc, 0x7a, + 0xd8, 0xcd, 0xd9, 0x43, 0xb8, 0x5c, 0x29, 0x97, 0x85, 0x8e, 0x9e, 0xfd, + 0x42, 0x32, 0x7d, 0xf0, 0xcc, 0x05, 0x45, 0x6f, 0x3f, 0xec, 0x79, 0xeb, + 0xe1, 0x98, 0x0a, 0x89, 0xc2, 0x47, 0xa3, 0xf8, 0x31, 0x8c, 0xde, 0x6d, + 0x69, 0xf7, 0xc3, 0x30, 0x15, 0x16, 0x8c, 0xfc, 0xd8, 0x3e, 0x73, 0x4b, + 0x4c, 0x5e, 0xd6, 0x9f, 0xff, 0x58, 0xda, 0x6e, 0x7e, 0xdb, 0xcb, 0x8d, + 0x76, 0xb4, 0xff, 0x9a, 0xdc, 0xeb, 0xec, 0x73, 0xaf, 0x62, 0xd0, 0xc8, + 0x9b, 0xda, 0xac, 0xa9, 0xc4, 0x6a, 0x5e, 0x16, 0x52, 0x3b, 0xbc, 0x9b, + 0xb5, 0x0b, 0x98, 0xc7, 0x71, 0x80, 0x4f, 0x06, 0x60, 0x2a, 0x2d, 0xa9, + 0xfb, 0x6c, 0x66, 0x2e, 0x56, 0x95, 0x7c, 0xf5, 0xf4, 0x57, 0x3f, 0xc7, + 0xf7, 0xef, 0x3f, 0xcf, 0x82, 0xb4, 0x1c, 0xf9, 0x7b, 0x27, 0x9f, 0xc7, + 0xaf, 0x86, 0x60, 0x2a, 0x2e, 0x59, 0xfc, 0x7a, 0xf8, 0x66, 0x02, 0xa2, + 0xed, 0x86, 0x6c, 0xd6, 0x2c, 0x28, 0x7c, 0xa2, 0xfe, 0x61, 0xbb, 0xee, + 0x5e, 0x71, 0x4f, 0xd6, 0xf5, 0xe3, 0x67, 0xdc, 0x73, 0xa3, 0x18, 0x55, + 0xc8, 0xf4, 0x79, 0x3f, 0x8f, 0x5f, 0x0c, 0xc0, 0x54, 0x54, 0xf3, 0x16, + 0x96, 0x9e, 0x0c, 0xc0, 0x54, 0x57, 0x33, 0xf8, 0xf5, 0xf0, 0xcc, 0x05, + 0x45, 0x9d, 0x1f, 0x3e, 0x7d, 0x95, 0xcf, 0xff, 0x56, 0x9a, 0xfd, 0x3c, + 0xbe, 0x99, 0xc7, 0x09, 0x69, 0xff, 0x6c, 0xbf, 0xce, 0xe8, 0x87, 0xda, + 0xd3, 0xef, 0x86, 0x60, 0x2a, 0x24, 0x29, 0xfe, 0x2b, 0x6f, 0xa1, 0x63, + 0x5d, 0x69, 0x9e, 0x7a, 0x3e, 0x9e, 0xcc, 0x67, 0x9d, 0xed, 0xb1, 0x96, + 0x9f, 0xd5, 0xbb, 0xde, 0xbf, 0x62, 0xd2, 0x3f, 0x2a, 0x88, 0x29, 0xf0, + 0x88, 0x9c, 0x53, 0xc8, 0x54, 0x5c, 0xbb, 0x44, 0xd3, 0xff, 0x8e, 0x6c, + 0x79, 0xeb, 0xe1, 0x98, 0x0a, 0x89, 0xf2, 0x01, 0x58, 0xff, 0x5e, 0x52, + 0xe6, 0xdc, 0x27, 0xdf, 0x0c, 0xc0, 0x54, 0x56, 0x53, 0xfe, 0xc7, 0x9e, + 0xbe, 0x19, 0x80, 0xa8, 0x9b, 0xa6, 0x23, 0xd1, 0xfc, 0x18, 0xc6, 0x7f, + 0xf1, 0xcd, 0x8f, 0x3d, 0x7c, 0x33, 0x01, 0x51, 0x2b, 0x4f, 0xf8, 0xaf, + 0xe1, 0x84, 0x9d, 0x79, 0x8b, 0x4f, 0xe1, 0x6f, 0xd3, 0xac, 0x32, 0xd0, + 0xf3, 0xf2, 0x24, 0x09, 0xf7, 0xc3, 0x30, 0x15, 0x12, 0xe4, 0xff, 0x16, + 0x3f, 0x42, 0xc6, 0xba, 0xd3, 0xce, 0x88, 0x59, 0x69, 0xf1, 0xcd, 0x8f, + 0x3b, 0x22, 0xa6, 0x88, 0x76, 0x63, 0x86, 0xd3, 0xff, 0x1f, 0x1e, 0x7a, + 0xf8, 0x66, 0x02, 0xa2, 0x3b, 0x9f, 0xed, 0x6e, 0x9e, 0x7c, 0x1b, 0xad, + 0x3f, 0x75, 0x82, 0xc1, 0x42, 0xb4, 0xde, 0x6d, 0x69, 0xf9, 0xdf, 0x1a, + 0xde, 0x69, 0x69, 0xfd, 0x5c, 0x5d, 0x87, 0x57, 0x5a, 0x7d, 0xf0, 0xcc, + 0x05, 0x45, 0x43, 0x3d, 0xbd, 0x55, 0x8b, 0x4f, 0xaa, 0xcc, 0x17, 0x4b, + 0x4f, 0xff, 0xff, 0xe6, 0x7f, 0x4d, 0x6c, 0x9a, 0xfd, 0x2b, 0xc0, 0x67, + 0x5d, 0x2b, 0xff, 0xa7, 0x5e, 0x66, 0xd6, 0x8a, 0x47, 0x08, 0x91, 0x5c, + 0xa2, 0x7f, 0xff, 0xbc, 0xce, 0xb9, 0x59, 0xbc, 0x2d, 0x36, 0xcb, 0x57, + 0xae, 0x56, 0x91, 0xdd, 0xf5, 0x4a, 0x2e, 0xf1, 0x77, 0x58, 0x2f, 0x61, + 0x85, 0x19, 0x6a, 0x31, 0x2e, 0xa2, 0xe9, 0xf7, 0xc3, 0x30, 0x15, 0x15, + 0x44, 0xff, 0xb1, 0xe7, 0xaf, 0x86, 0x60, 0x2a, 0x26, 0xb9, 0x1e, 0x8f, + 0xe0, 0xc6, 0x33, 0xf8, 0xf5, 0xf0, 0xcc, 0x05, 0x45, 0x59, 0x3f, 0xf1, + 0xf1, 0xe7, 0xaf, 0x86, 0x60, 0x2a, 0x24, 0x49, 0xf7, 0xc3, 0x30, 0x15, + 0x16, 0x94, 0xff, 0xb1, 0xe7, 0xaf, 0x86, 0x60, 0x2a, 0x27, 0xd9, 0x1e, + 0x8f, 0xe0, 0xc6, 0x33, 0xff, 0x8e, 0x6c, 0x79, 0xeb, 0xe1, 0x98, 0x0a, + 0x8a, 0x12, 0x7d, 0xb2, 0xb1, 0xbe, 0xb4, 0xfb, 0xe1, 0x98, 0x0a, 0x8a, + 0x3e, 0x7f, 0xc2, 0xce, 0x30, 0xb3, 0x9b, 0x65, 0xa7, 0xff, 0xea, 0xe7, + 0x6d, 0xe8, 0xfa, 0x1c, 0xee, 0xf7, 0x6e, 0xd2, 0x9f, 0x1c, 0xd8, 0xf3, + 0xb2, 0x3c, 0xa8, 0x9f, 0x46, 0x3d, 0x47, 0x90, 0xcc, 0x88, 0x5b, 0x23, + 0x6e, 0x7a, 0xbd, 0x26, 0xfb, 0x95, 0x10, 0x10, 0xfc, 0xb4, 0x9d, 0xc3, + 0xcd, 0xc3, 0x17, 0xb2, 0x7d, 0x46, 0x8b, 0x3f, 0x8f, 0x5f, 0x0c, 0xc0, + 0x54, 0x44, 0x53, 0xf5, 0x7c, 0x33, 0x01, 0x51, 0x15, 0xcf, 0xf7, 0x5c, + 0xf5, 0xf0, 0xcc, 0x05, 0x45, 0x71, 0x07, 0x3f, 0xcc, 0x36, 0x9e, 0xad, + 0xe6, 0x96, 0x9f, 0xd4, 0x5f, 0xef, 0xbf, 0x2e, 0xb4, 0x9d, 0xf1, 0x3d, + 0x5b, 0x90, 0x4f, 0xff, 0xda, 0xb9, 0x6f, 0x09, 0xe4, 0x3a, 0xf3, 0x7f, + 0xa5, 0xa7, 0xdf, 0x0c, 0xc0, 0x54, 0x53, 0xd3, 0xf5, 0x5f, 0xa0, 0xe3, + 0xd6, 0x8e, 0xb1, 0x1c, 0x6c, 0x59, 0x4b, 0x22, 0x63, 0x3f, 0xfb, 0x1e, + 0x7e, 0x47, 0x38, 0xbd, 0xdb, 0xb5, 0xa0, 0xe8, 0x8a, 0xe4, 0xfe, 0x71, + 0xf9, 0xa5, 0xa7, 0xcc, 0xfe, 0xfc, 0x7a, 0xd3, 0xc1, 0x98, 0x0a, 0x8a, + 0xce, 0x1c, 0x3d, 0x4f, 0x94, 0xcf, 0xd6, 0x19, 0x85, 0xf7, 0x5a, 0x73, + 0x58, 0x4b, 0x4f, 0xb5, 0xdf, 0xa1, 0x7a, 0xd3, 0xbc, 0xcb, 0xad, 0x3e, + 0xa7, 0x2c, 0xf3, 0xb5, 0xa4, 0x7a, 0x46, 0xe7, 0xc8, 0xf6, 0x5b, 0x83, + 0x62, 0x55, 0xe8, 0x72, 0x7f, 0xe3, 0xe3, 0xcf, 0x5f, 0x0c, 0xc0, 0x54, + 0x48, 0xb3, 0xf5, 0x7c, 0x33, 0x01, 0x51, 0x64, 0xcf, 0xfe, 0xd5, 0xfd, + 0x5c, 0xf5, 0x61, 0x0b, 0xee, 0xb4, 0x1d, 0x10, 0x54, 0x6d, 0x3f, 0x8f, + 0x5f, 0x0c, 0xc0, 0x54, 0x5b, 0x13, 0xaa, 0xf4, 0xb4, 0xf0, 0x66, 0x02, + 0xa2, 0xdb, 0x9e, 0xbd, 0x99, 0xf5, 0xa3, 0xe7, 0x9b, 0xa2, 0xb9, 0x1d, + 0xe8, 0x89, 0xa6, 0x79, 0xd6, 0x6c, 0x96, 0x9f, 0xf7, 0x59, 0xd6, 0x3b, + 0xbd, 0x6e, 0x85, 0xbb, 0x5a, 0x7e, 0x61, 0x7f, 0x3e, 0x19, 0x69, 0xf7, + 0xc3, 0x30, 0x15, 0x17, 0x84, 0xf6, 0xba, 0xab, 0x6b, 0x4f, 0xfc, 0xde, + 0x8d, 0x6b, 0xf5, 0x43, 0xab, 0xad, 0x3e, 0xa1, 0xed, 0xd9, 0x96, 0x9f, + 0x37, 0xaf, 0x32, 0xeb, 0x4e, 0xd3, 0x76, 0xb4, 0x8f, 0xd6, 0x27, 0x43, + 0xd6, 0xa1, 0xcb, 0x13, 0xa8, 0xba, 0xd3, 0x1d, 0x92, 0x76, 0x8c, 0x25, + 0x3a, 0x29, 0x9c, 0x55, 0x6a, 0xd3, 0xef, 0x86, 0x60, 0x2a, 0x2f, 0x49, + 0xff, 0x0e, 0x69, 0xed, 0xef, 0x45, 0x62, 0xd3, 0xea, 0x36, 0xf3, 0x95, + 0xa4, 0x7e, 0x51, 0x65, 0x43, 0x7e, 0x8c, 0x5d, 0x8f, 0xe1, 0x99, 0x2e, + 0x76, 0x42, 0xe2, 0xa3, 0xe3, 0x02, 0x42, 0x8d, 0x33, 0xeb, 0x86, 0x86, + 0x7f, 0x64, 0x43, 0x0c, 0x5f, 0x23, 0xc9, 0xe2, 0x34, 0x59, 0xbc, 0xda, + 0xd3, 0xd5, 0xbc, 0xd2, 0xd3, 0xfa, 0x8b, 0xfd, 0xf7, 0xe5, 0xd6, 0x93, + 0xbe, 0x27, 0xab, 0x72, 0x09, 0xf1, 0x69, 0xad, 0xb1, 0x69, 0xf7, 0xc3, + 0x30, 0x15, 0x11, 0x1c, 0xff, 0xf6, 0xfc, 0xbd, 0xe8, 0xc3, 0x4e, 0xba, + 0x33, 0xba, 0x5a, 0x7f, 0xcf, 0x6b, 0x3f, 0x5a, 0xd1, 0x69, 0x69, 0xfe, + 0xaf, 0xd5, 0xeb, 0x06, 0xc5, 0xa7, 0xff, 0xf9, 0xb7, 0x85, 0xa6, 0xd8, + 0xd6, 0xb6, 0x5b, 0xa2, 0xe1, 0x69, 0xac, 0x32, 0x53, 0x71, 0xc2, 0x53, + 0xfe, 0x38, 0x6c, 0x9c, 0xdb, 0x58, 0x7e, 0xcd, 0x7f, 0x02, 0xf3, 0xce, + 0x9b, 0x4c, 0xb4, 0x3c, 0xfe, 0x89, 0x62, 0x7e, 0xeb, 0x8d, 0x6f, 0x34, + 0xb4, 0xfc, 0xde, 0xe8, 0x4b, 0xda, 0xd3, 0xf5, 0x69, 0xdb, 0x55, 0xb5, + 0xa2, 0x91, 0x18, 0x25, 0xf7, 0x2e, 0x9f, 0xff, 0x80, 0xff, 0xc1, 0x2d, + 0x1f, 0xed, 0xa1, 0xce, 0xd6, 0x87, 0x79, 0x5f, 0xe7, 0x58, 0xd8, 0xc5, + 0x94, 0x50, 0x06, 0x36, 0xac, 0x91, 0xf7, 0xcd, 0xb2, 0x30, 0xbd, 0x42, + 0xb5, 0xd1, 0x74, 0xfb, 0xe1, 0x98, 0x0a, 0x88, 0xba, 0x7d, 0xae, 0xfd, + 0x0b, 0xd2, 0x91, 0xe8, 0xf6, 0xf0, 0xc6, 0x0e, 0x99, 0x73, 0xe3, 0x08, + 0x9f, 0xf8, 0xd8, 0xf3, 0xd7, 0xc3, 0x30, 0x15, 0x13, 0x34, 0xfd, 0xd6, + 0x8e, 0xed, 0xdf, 0xbb, 0x69, 0x69, 0xd6, 0xb5, 0xd6, 0x9c, 0x04, 0x65, + 0xa6, 0xea, 0xeb, 0x6b, 0x4f, 0xda, 0xab, 0x2b, 0xb7, 0x16, 0x8e, 0xb6, + 0x79, 0xce, 0x0f, 0xcf, 0x83, 0x36, 0x4e, 0x2d, 0x3f, 0xfe, 0xee, 0xd7, + 0xef, 0xc6, 0xf9, 0xf6, 0x41, 0x9f, 0x5a, 0x7f, 0xe7, 0x62, 0xd1, 0x01, + 0x73, 0xaa, 0x05, 0xa7, 0xff, 0xfb, 0xcc, 0x10, 0x1a, 0xe7, 0x7e, 0x74, + 0xdb, 0x3f, 0xed, 0x62, 0xd0, 0xc9, 0x82, 0x52, 0xbe, 0xd1, 0x27, 0xff, + 0xdc, 0x90, 0xd9, 0x57, 0x2c, 0xd9, 0xf8, 0xe3, 0x84, 0xa7, 0xeb, 0x5f, + 0x7e, 0xfc, 0x71, 0x69, 0xe0, 0xcc, 0x05, 0x45, 0x9f, 0x3f, 0xe2, 0xdb, + 0x3c, 0xb4, 0xda, 0xba, 0xd3, 0xff, 0xc5, 0xfd, 0xe7, 0x4a, 0x74, 0x35, + 0x7a, 0x15, 0xa7, 0x71, 0xc7, 0x09, 0x4f, 0xfb, 0x1f, 0x71, 0xa0, 0xe6, + 0xbe, 0x91, 0xcb, 0xf9, 0xfe, 0x6d, 0x97, 0x23, 0x98, 0xe2, 0xd3, 0xfc, + 0x43, 0xcf, 0xae, 0x7c, 0xd5, 0xd6, 0x80, 0x54, 0x3c, 0xe2, 0xc7, 0xcc, + 0x8c, 0x57, 0xb3, 0xce, 0xdb, 0xb4, 0x96, 0xe8, 0xde, 0x7f, 0xbf, 0x9c, + 0x6c, 0x9b, 0xec, 0xb4, 0xff, 0xff, 0xfd, 0x55, 0xdd, 0xea, 0x87, 0xdf, + 0xaf, 0x8b, 0x56, 0xcf, 0x71, 0xab, 0x0d, 0x46, 0x5a, 0x75, 0xda, 0xc5, + 0xa7, 0x75, 0x56, 0xd6, 0x87, 0xa3, 0x0e, 0xf0, 0x89, 0xd0, 0xe4, 0xed, + 0xf9, 0xc2, 0xd3, 0xbb, 0xf0, 0x16, 0x9d, 0xaa, 0xf4, 0xb4, 0x72, 0x7b, + 0x16, 0x8f, 0x10, 0xec, 0xfd, 0xf2, 0x75, 0x43, 0x75, 0xa7, 0xdb, 0x16, + 0xaf, 0xa9, 0x3f, 0xe2, 0xfb, 0xeb, 0xf6, 0x79, 0x9c, 0xaa, 0x20, 0xd3, + 0x9a, 0x59, 0xf6, 0x01, 0x19, 0x96, 0x9f, 0x9f, 0xb1, 0xcb, 0x74, 0xb4, + 0xa8, 0x0f, 0x44, 0x49, 0x27, 0xfe, 0xa1, 0xb7, 0x55, 0xf2, 0xb3, 0x0c, + 0xb4, 0xc4, 0x2b, 0x4f, 0xd9, 0xc6, 0xab, 0x7a, 0x63, 0xd7, 0xf6, 0x87, + 0x0c, 0x9e, 0x13, 0xd4, 0xaa, 0x15, 0xc2, 0xf9, 0x3f, 0x7e, 0xb9, 0xbe, + 0xd9, 0x69, 0xff, 0xfd, 0xe0, 0xe7, 0xbe, 0x9e, 0x87, 0x35, 0x72, 0xb7, + 0x65, 0xc2, 0xd3, 0xfe, 0x35, 0x6a, 0xfe, 0xaf, 0x8f, 0xa5, 0xa7, 0xeb, + 0xdd, 0xbf, 0xa6, 0x58, 0xe6, 0xfe, 0x7b, 0x74, 0x4e, 0x96, 0x9f, 0xae, + 0x5f, 0xaf, 0x3e, 0xb4, 0x12, 0x22, 0xf6, 0x79, 0xa2, 0x29, 0x8c, 0xef, + 0xaa, 0x2f, 0xc9, 0xff, 0x9f, 0xaf, 0x1e, 0xf3, 0x6b, 0x4c, 0x65, 0xa7, + 0xfe, 0x2a, 0x1a, 0xab, 0xf4, 0x7d, 0xcc, 0xb4, 0x5a, 0x88, 0x9b, 0xa3, + 0x4c, 0x4e, 0x2d, 0x3b, 0x45, 0x62, 0xd3, 0x85, 0x81, 0x68, 0xe8, 0x79, + 0x66, 0x16, 0x11, 0xc8, 0x64, 0xdf, 0xf9, 0x2f, 0xa8, 0x58, 0xe3, 0x7c, + 0xff, 0xff, 0xce, 0xcd, 0xb2, 0x31, 0xdc, 0x7e, 0x7f, 0xd6, 0xca, 0xdb, + 0x81, 0x58, 0xb4, 0xfd, 0x9f, 0x6d, 0xfa, 0xe5, 0x69, 0xee, 0x32, 0xae, + 0xb4, 0xff, 0x3c, 0xd8, 0xfd, 0x5d, 0xbd, 0xad, 0x0c, 0x7b, 0x78, 0x43, + 0x3d, 0x57, 0x21, 0x5a, 0x31, 0x19, 0x23, 0x08, 0xaf, 0x08, 0x27, 0xbd, + 0x79, 0x97, 0x5a, 0x7e, 0x76, 0xd5, 0x60, 0x82, 0xd3, 0xfd, 0x7e, 0xca, + 0xdb, 0x5f, 0x5a, 0x5a, 0x36, 0x7d, 0x1a, 0x2d, 0x86, 0x45, 0x75, 0x42, + 0x32, 0x67, 0x3c, 0x5a, 0x46, 0x5a, 0x2d, 0x35, 0x0e, 0xe0, 0xc4, 0xfe, + 0xcc, 0xb5, 0xe2, 0xdc, 0xad, 0x3f, 0xf8, 0x49, 0xae, 0x38, 0xfe, 0x97, + 0xaf, 0xad, 0x3f, 0xff, 0xed, 0x95, 0xba, 0xab, 0x75, 0xff, 0xb6, 0xbb, + 0xf4, 0x2f, 0xdd, 0x2d, 0x3d, 0xcf, 0x38, 0x2b, 0x4f, 0xfb, 0x36, 0x05, + 0x9d, 0x2f, 0x9b, 0x5a, 0x19, 0x37, 0x0e, 0x49, 0xe8, 0xc8, 0x12, 0x09, + 0xc3, 0x64, 0x53, 0xff, 0x50, 0xdb, 0xaa, 0xf9, 0x59, 0x86, 0x5a, 0x7d, + 0x5a, 0x79, 0xb6, 0xb4, 0xfa, 0xdb, 0x8b, 0x19, 0x68, 0x64, 0x48, 0xdd, + 0x0f, 0xc2, 0x79, 0xbb, 0xda, 0xd3, 0xf5, 0x8e, 0x3f, 0xac, 0xfd, 0x8b, + 0x4f, 0xef, 0x7b, 0xad, 0x6c, 0xb4, 0xb4, 0xc5, 0xf5, 0xa3, 0xad, 0x9f, + 0xf9, 0x1b, 0x6c, 0xd2, 0x7f, 0xee, 0x5b, 0x9f, 0xb6, 0x88, 0x0b, 0x95, + 0xa7, 0xed, 0xf9, 0x63, 0x9b, 0x25, 0xa3, 0x93, 0xf4, 0xda, 0x24, 0x8f, + 0xd6, 0xdb, 0x20, 0x87, 0x78, 0xfd, 0xdd, 0x8e, 0x33, 0x45, 0x85, 0x3c, + 0xc6, 0x55, 0x52, 0x93, 0x7d, 0xbb, 0x5b, 0x0f, 0xa2, 0x84, 0x6b, 0x91, + 0xf9, 0x7d, 0x00, 0xc5, 0xbb, 0x95, 0x61, 0x88, 0x3d, 0xc6, 0x82, 0x30, + 0xe2, 0xbc, 0x77, 0xda, 0x87, 0x37, 0x06, 0x1d, 0x50, 0x96, 0xf5, 0x0a, + 0x88, 0x3b, 0x67, 0xc9, 0xba, 0xc9, 0x56, 0x7f, 0xf1, 0xcd, 0x8f, 0x3d, + 0x7c, 0x33, 0x01, 0x51, 0x36, 0x4f, 0xe3, 0xd7, 0xc3, 0x30, 0x15, 0x15, + 0x6c, 0xfe, 0x7b, 0xfc, 0xd0, 0xb3, 0xd6, 0x9e, 0xad, 0xe6, 0x96, 0x93, + 0xbf, 0x47, 0xa6, 0x26, 0x73, 0xef, 0x86, 0x60, 0x2a, 0x2b, 0x49, 0xff, + 0xe0, 0x6f, 0xd7, 0x78, 0x6c, 0x7b, 0x10, 0x2d, 0x3f, 0xfc, 0xfb, 0xd0, + 0xb1, 0xb2, 0xb5, 0xa6, 0x32, 0xd3, 0x6b, 0x4c, 0x89, 0x7c, 0x4b, 0x9f, + 0xcc, 0xeb, 0xd6, 0x85, 0xbb, 0x5a, 0x7e, 0xb2, 0xb6, 0x54, 0x65, 0xa7, + 0xfa, 0x9d, 0x85, 0xb8, 0xb5, 0xf7, 0x5a, 0x7f, 0x3e, 0xb5, 0x83, 0xdf, + 0x8b, 0x48, 0xfd, 0x62, 0x7e, 0x34, 0x56, 0x50, 0xc8, 0xd9, 0x6e, 0x1b, + 0x09, 0x66, 0x8f, 0x27, 0xf1, 0xeb, 0xe1, 0x98, 0x0a, 0x8b, 0x02, 0x7d, + 0xf0, 0xcc, 0x05, 0x44, 0xeb, 0x3f, 0xff, 0xb6, 0xd6, 0x73, 0x46, 0x3d, + 0xef, 0x5b, 0x2b, 0xf9, 0x62, 0xd3, 0xe3, 0x9b, 0x1e, 0x7a, 0x44, 0xab, + 0x86, 0x33, 0xf9, 0xf7, 0x3f, 0xbf, 0x6c, 0x65, 0xa7, 0xdf, 0x0c, 0xc0, + 0x54, 0x5b, 0x33, 0xfe, 0xed, 0xae, 0x7d, 0x90, 0x67, 0xd6, 0x91, 0xe8, + 0xfb, 0xb0, 0xc6, 0x78, 0x33, 0x01, 0x51, 0x73, 0x48, 0xcb, 0x47, 0xcd, + 0xdf, 0x05, 0x73, 0x38, 0x65, 0xa4, 0x7a, 0x37, 0x3c, 0x11, 0x4f, 0xe3, + 0xd7, 0xc3, 0x30, 0x15, 0x17, 0x7c, 0xf1, 0xfd, 0xf3, 0xda, 0xd0, 0xcd, + 0xd2, 0xed, 0x56, 0x81, 0xc0, 0x65, 0x6a, 0x99, 0x4a, 0x80, 0xfb, 0x89, + 0xa1, 0xa3, 0x88, 0x1d, 0xc2, 0x96, 0xf0, 0x9a, 0xd1, 0x3f, 0xa3, 0xc9, + 0xf5, 0xee, 0x6c, 0x7a, 0xd3, 0xff, 0x5a, 0x1e, 0x65, 0xba, 0xaa, 0x1f, + 0x6b, 0x4e, 0x1c, 0x3b, 0x1f, 0x6e, 0x89, 0xe7, 0xf0, 0xd9, 0x4e, 0xda, + 0x6f, 0x6b, 0x4f, 0xbe, 0x19, 0x80, 0xa8, 0x95, 0xe7, 0xfc, 0x39, 0xc7, + 0x3b, 0x6b, 0x2b, 0x85, 0xa7, 0xff, 0xe7, 0xd1, 0x77, 0x46, 0x2d, 0x5d, + 0x8d, 0x96, 0xe9, 0x69, 0xef, 0x33, 0xef, 0x5a, 0x7f, 0xff, 0x16, 0xb0, + 0xd8, 0x3d, 0xef, 0x8c, 0x1b, 0x00, 0xac, 0x5a, 0x39, 0x44, 0x16, 0x11, + 0x47, 0x29, 0x9f, 0xd2, 0x06, 0xe1, 0xb9, 0x3b, 0x1e, 0x76, 0x4f, 0x76, + 0x8d, 0xef, 0x1b, 0x84, 0xed, 0x37, 0x29, 0x4f, 0xfe, 0xde, 0x16, 0x99, + 0xe5, 0xfb, 0x3c, 0xed, 0x29, 0xfd, 0x80, 0x7e, 0x7e, 0xee, 0x1d, 0x8f, + 0x9e, 0xe3, 0x92, 0x38, 0x2b, 0x0a, 0x34, 0xa0, 0xe7, 0x50, 0xad, 0x9f, + 0xfc, 0x73, 0x63, 0xcf, 0x5f, 0x0c, 0xc0, 0x54, 0x4c, 0x33, 0xff, 0x85, + 0x9d, 0x0b, 0x5a, 0x7e, 0xb6, 0xee, 0xee, 0xf5, 0xa7, 0xff, 0x7f, 0x3b, + 0x3f, 0xbd, 0x3f, 0x86, 0xbb, 0xd6, 0x9a, 0x8f, 0xca, 0x29, 0x7d, 0x2b, + 0xcf, 0xfc, 0xef, 0xd5, 0xaf, 0xf3, 0x34, 0x2c, 0xf5, 0xa7, 0xf3, 0x65, + 0x9a, 0xf7, 0x9f, 0x5a, 0x7d, 0x9f, 0x7e, 0x19, 0x68, 0x13, 0xda, 0xf0, + 0xd2, 0x7e, 0x33, 0x50, 0xeb, 0xa9, 0x69, 0x5d, 0x69, 0xf3, 0x50, 0xeb, + 0xa9, 0x69, 0xfb, 0x65, 0xab, 0xe5, 0xbd, 0x0f, 0x99, 0xc2, 0xe3, 0x08, + 0x4f, 0xff, 0xf8, 0x6b, 0x87, 0x6d, 0x56, 0xfa, 0x0d, 0x58, 0x54, 0x36, + 0xbe, 0xeb, 0x4f, 0xff, 0x36, 0x87, 0x3b, 0xdd, 0x17, 0x3e, 0x6a, 0xeb, + 0x4f, 0xce, 0xbd, 0x68, 0x5b, 0xb5, 0xa7, 0xff, 0x36, 0xbb, 0x67, 0xd5, + 0xba, 0xb3, 0xce, 0x16, 0x86, 0x3f, 0xf2, 0x31, 0x9f, 0xae, 0x5e, 0xcd, + 0x9a, 0x5a, 0x7f, 0xff, 0xdf, 0xa7, 0x4c, 0x3a, 0xe9, 0xe8, 0x5b, 0x78, + 0x5a, 0x6d, 0x5d, 0x69, 0x55, 0xa8, 0x9c, 0xf9, 0x74, 0xff, 0xfb, 0x63, + 0x5a, 0xd9, 0x55, 0xba, 0xa7, 0x4d, 0x75, 0xa7, 0x37, 0x7e, 0x96, 0x8a, + 0x3f, 0x31, 0x55, 0x9e, 0xcf, 0x5c, 0xd2, 0xd2, 0x3f, 0x58, 0xb8, 0xb5, + 0xcc, 0x28, 0xc2, 0x11, 0x0e, 0x2a, 0xfd, 0xc3, 0x70, 0xcf, 0x18, 0x5e, + 0x6a, 0x13, 0x9e, 0x10, 0x4f, 0xbe, 0x19, 0x80, 0xa8, 0xab, 0xa7, 0xf9, + 0xe7, 0xaf, 0x86, 0x60, 0x2a, 0x23, 0xc9, 0x1e, 0x8f, 0xcf, 0x0c, 0x67, + 0xf1, 0xeb, 0xe1, 0x98, 0x0a, 0x8b, 0x06, 0x7f, 0x1e, 0xbe, 0x19, 0x80, + 0xa8, 0xb2, 0xa7, 0xf1, 0xeb, 0xe1, 0x98, 0x0a, 0x8b, 0x4e, 0x7f, 0x55, + 0xfa, 0x7f, 0xfe, 0x6d, 0x69, 0xe0, 0xcc, 0x05, 0x45, 0xb9, 0x3f, 0xf3, + 0x57, 0xe8, 0x7a, 0x6e, 0xad, 0xe1, 0x68, 0xf9, 0xf8, 0x5c, 0xae, 0x7f, + 0x98, 0x7c, 0x33, 0x5f, 0x44, 0xb4, 0xfe, 0xcc, 0xb3, 0x96, 0xaf, 0xad, + 0x3f, 0xec, 0x79, 0xeb, 0xe1, 0x98, 0x0a, 0x8a, 0x1e, 0x7f, 0xe3, 0x67, + 0x2d, 0xce, 0xc8, 0x48, 0xcb, 0x4f, 0xfd, 0xe3, 0xf7, 0x9f, 0xb7, 0x4c, + 0x56, 0x2d, 0x3f, 0xef, 0x3f, 0xdf, 0xf0, 0x75, 0x5d, 0xad, 0x3f, 0x5f, + 0x2d, 0xbe, 0x89, 0x69, 0xf8, 0x7a, 0xca, 0xfb, 0x5d, 0x69, 0xff, 0xfa, + 0xb9, 0xdb, 0x7a, 0x3e, 0x87, 0x3b, 0xbd, 0xdb, 0xb4, 0xa4, 0x77, 0xaa, + 0xfc, 0xa8, 0x53, 0x11, 0x13, 0x86, 0xe6, 0x32, 0xc4, 0x7e, 0xd0, 0xee, + 0x8d, 0xa4, 0x0f, 0x0b, 0x7a, 0x8c, 0x27, 0xf1, 0xeb, 0xe1, 0x98, 0x0a, + 0x8b, 0xce, 0x19, 0x97, 0x36, 0xf4, 0x5e, 0x61, 0xf1, 0x53, 0x91, 0x76, + 0xc6, 0x33, 0xf2, 0x63, 0x1e, 0x6c, 0xf0, 0x65, 0x9c, 0x3a, 0x85, 0x44, + 0xfe, 0x3d, 0x7c, 0x33, 0x01, 0x51, 0x4b, 0x4f, 0xe3, 0xd7, 0xc3, 0x30, + 0x15, 0x16, 0x14, 0xfe, 0x3d, 0x7c, 0x33, 0x01, 0x51, 0x65, 0xcf, 0x1f, + 0xdf, 0x5a, 0x3b, 0xa5, 0xa7, 0x1f, 0xd1, 0x96, 0x95, 0xc0, 0xf3, 0xfc, + 0x31, 0x9f, 0x67, 0xeb, 0xdd, 0x8b, 0x4f, 0xf0, 0xb7, 0x0d, 0x4e, 0x9a, + 0xeb, 0x4f, 0xd9, 0xf6, 0xd6, 0x6d, 0x69, 0x9a, 0xeb, 0x46, 0xcf, 0x01, + 0xd1, 0x5c, 0xfc, 0x59, 0x7e, 0xef, 0xe2, 0xd2, 0x7a, 0xd2, 0x7a, 0xd2, + 0x7a, 0xd0, 0xc6, 0xc3, 0xd8, 0x81, 0x08, 0x4c, 0x4c, 0xb4, 0xfc, 0x2c, + 0x61, 0x6a, 0x5a, 0x39, 0x37, 0xae, 0x0a, 0x4c, 0xc6, 0x5a, 0x7f, 0xfe, + 0x7b, 0x0f, 0x8f, 0x7b, 0x6b, 0x74, 0x6f, 0x4d, 0xda, 0xd3, 0x01, 0xd9, + 0x52, 0x5d, 0x85, 0x1c, 0x94, 0xd3, 0xc0, 0x12, 0x62, 0xf5, 0xda, 0xfa, + 0x88, 0xfd, 0x0a, 0xcf, 0xfe, 0x39, 0xb1, 0xe7, 0xaf, 0x86, 0x60, 0x2a, + 0x28, 0xc9, 0xfc, 0x76, 0x74, 0xdf, 0x6e, 0xd6, 0x87, 0xae, 0x31, 0xfc, + 0xf0, 0xc7, 0x99, 0x2b, 0x5a, 0xf0, 0x8e, 0xd2, 0x9c, 0xff, 0xc7, 0xc7, + 0x9e, 0xbe, 0x19, 0x80, 0xa8, 0x8e, 0x67, 0xff, 0x1c, 0xd8, 0xf3, 0xd7, + 0xc3, 0x30, 0x15, 0x13, 0x94, 0xfe, 0x3d, 0x7c, 0x33, 0x01, 0x51, 0x66, + 0x4f, 0xf7, 0x7f, 0x6d, 0x6f, 0x2d, 0x7a, 0xd3, 0xfa, 0xaf, 0xff, 0xd5, + 0xb7, 0x5a, 0x47, 0x63, 0xed, 0x79, 0xd4, 0xfe, 0x3d, 0x7c, 0x33, 0x01, + 0x51, 0x6e, 0xcf, 0xfe, 0x39, 0xb1, 0xe7, 0xaf, 0x86, 0x60, 0x2a, 0x29, + 0x09, 0xff, 0x8f, 0x8f, 0x3d, 0x7c, 0x33, 0x01, 0x51, 0x29, 0x45, 0x8a, + 0x93, 0x1c, 0x4d, 0x32, 0x9f, 0x70, 0xa9, 0x12, 0x7d, 0x1e, 0x3b, 0x29, + 0xcf, 0xfb, 0x1e, 0x7a, 0xf8, 0x66, 0x02, 0xa2, 0x76, 0x9f, 0xff, 0x17, + 0x3e, 0x19, 0x9d, 0xb3, 0x91, 0x61, 0xa0, 0x5a, 0x47, 0x32, 0x27, 0x71, + 0x1e, 0x7f, 0xec, 0x36, 0xe8, 0x33, 0x6d, 0xe9, 0xeb, 0x4f, 0xfc, 0x35, + 0xbc, 0xb2, 0xae, 0x39, 0x6a, 0xd3, 0x75, 0x1f, 0x94, 0x42, 0xdd, 0x0e, + 0x0c, 0x8e, 0x0e, 0xa8, 0x56, 0xcf, 0xbe, 0x19, 0x80, 0xa8, 0x8b, 0x27, + 0xfd, 0x8f, 0x3d, 0x7c, 0x33, 0x01, 0x51, 0x2e, 0xcf, 0xff, 0xd5, 0xce, + 0xdb, 0xd1, 0xf4, 0x39, 0xdd, 0xee, 0xdd, 0xa5, 0x23, 0xd2, 0x35, 0x8c, + 0x63, 0xd4, 0x8f, 0x3f, 0xf8, 0xe6, 0xc7, 0x9e, 0xbe, 0x19, 0x80, 0xa8, + 0x98, 0xa7, 0xdf, 0x0c, 0xc0, 0x54, 0x55, 0x32, 0xa5, 0xa2, 0x8f, 0x03, + 0xd9, 0x8c, 0xff, 0xff, 0xef, 0xe6, 0xed, 0x7d, 0x68, 0xfb, 0xcb, 0xfc, + 0xb8, 0xd6, 0xcb, 0xef, 0x5a, 0x0e, 0x89, 0xcc, 0x23, 0x9f, 0xfc, 0x73, + 0x63, 0xcf, 0x5f, 0x0c, 0xc0, 0x54, 0x4e, 0x93, 0xf8, 0xb3, 0xec, 0xfc, + 0x74, 0xb4, 0xf9, 0xc6, 0x71, 0xae, 0xb4, 0xfd, 0xc5, 0x13, 0xaa, 0x15, + 0xa0, 0x8f, 0x56, 0xe5, 0x13, 0x8b, 0x6c, 0xb1, 0xcd, 0x0c, 0xff, 0xde, + 0x5f, 0x4d, 0x69, 0xfc, 0x70, 0x8c, 0xb4, 0x18, 0xfc, 0xb6, 0x55, 0x3f, + 0xec, 0x79, 0xeb, 0xe1, 0x98, 0x0a, 0x89, 0xde, 0x7d, 0xaf, 0x30, 0xc4, + 0x94, 0x8f, 0xca, 0x75, 0x55, 0x18, 0xd1, 0x88, 0xb1, 0x1e, 0x7f, 0xf1, + 0xcd, 0x8f, 0x3d, 0x7c, 0x33, 0x01, 0x51, 0x42, 0xcf, 0xfe, 0x39, 0xb1, + 0xe7, 0xaf, 0x86, 0x60, 0x2a, 0x29, 0x29, 0xff, 0xfd, 0x57, 0x3f, 0xaa, + 0x73, 0x78, 0x6d, 0x6d, 0xb5, 0xe1, 0x96, 0x8b, 0x17, 0x36, 0x5e, 0x70, + 0x11, 0x97, 0xfc, 0x88, 0xd1, 0xfe, 0xf6, 0x93, 0xe2, 0x9f, 0x52, 0x9c, + 0xfe, 0x3d, 0x7c, 0x33, 0x01, 0x51, 0x12, 0x4f, 0xfe, 0x39, 0xb1, 0xe7, + 0xaf, 0x86, 0x60, 0x2a, 0x25, 0xe9, 0xf7, 0xfb, 0x31, 0x5d, 0x69, 0xdd, + 0xb6, 0x96, 0x9f, 0xfb, 0x1c, 0xbb, 0x3a, 0xcd, 0xb5, 0xae, 0x2d, 0x04, + 0x88, 0xb7, 0x0a, 0x3e, 0x39, 0x3f, 0xc5, 0x83, 0xe6, 0x9c, 0x6f, 0x6b, + 0x4f, 0xbe, 0x19, 0x80, 0xa8, 0xa5, 0xe7, 0xc3, 0xab, 0x2b, 0x85, 0xa7, + 0xfb, 0xbb, 0xfd, 0xad, 0x79, 0x19, 0x69, 0xfe, 0xcb, 0x3a, 0x59, 0xe3, + 0x8d, 0xd7, 0x5a, 0x6a, 0x7b, 0x1f, 0xe7, 0x87, 0x53, 0x3e, 0x96, 0x9c, + 0xdd, 0xdd, 0x68, 0xe4, 0xd8, 0xf0, 0x2b, 0x3f, 0xf1, 0x1b, 0x39, 0xf4, + 0xe3, 0xd8, 0x6d, 0x5a, 0x7a, 0xe5, 0xc6, 0x96, 0x8d, 0x9f, 0x4e, 0x91, + 0xe7, 0xfb, 0x37, 0x8e, 0x17, 0xda, 0xc5, 0xa7, 0xce, 0xc4, 0x66, 0xba, + 0xd3, 0xec, 0x75, 0x5f, 0xba, 0xd2, 0x6e, 0x4f, 0x44, 0xc5, 0x32, 0x3b, + 0x2a, 0xfc, 0xe4, 0xc2, 0x8e, 0xad, 0x31, 0x72, 0x14, 0x9b, 0x5e, 0xc8, + 0x46, 0x5c, 0x8b, 0x50, 0x89, 0x9f, 0xc7, 0xaf, 0x86, 0x60, 0x2a, 0x29, + 0xc9, 0xff, 0x17, 0xf2, 0xfb, 0xaa, 0x10, 0x5a, 0x7f, 0xd5, 0xb6, 0xfd, + 0x1f, 0x8e, 0x38, 0x4a, 0x62, 0xe1, 0x69, 0xac, 0x3f, 0x28, 0x90, 0xea, + 0x3a, 0x76, 0x40, 0x9f, 0x7c, 0x33, 0x01, 0x51, 0x5e, 0x4f, 0xff, 0xd5, + 0xce, 0xdb, 0xd1, 0xf4, 0x39, 0xdd, 0xee, 0xdd, 0xa5, 0x23, 0xd2, 0x23, + 0xfa, 0x8c, 0x67, 0xfe, 0x3e, 0x3c, 0xf5, 0xf0, 0xcc, 0x05, 0x44, 0x8f, + 0x38, 0xbb, 0x65, 0xa7, 0x05, 0x19, 0x23, 0x97, 0x73, 0xef, 0x86, 0x60, + 0x2a, 0x24, 0x89, 0xe3, 0xe3, 0xce, 0xc7, 0xb5, 0x45, 0x33, 0xff, 0x1f, + 0x1e, 0x7a, 0xf8, 0x66, 0x02, 0xa2, 0x4a, 0x9f, 0x7c, 0x33, 0x01, 0x51, + 0x78, 0xcf, 0xaf, 0x7d, 0x50, 0x2d, 0x3f, 0xcf, 0x3d, 0x7c, 0x33, 0x01, + 0x51, 0x26, 0xc8, 0xf4, 0x89, 0x9f, 0x98, 0xe1, 0x34, 0x33, 0x22, 0x22, + 0xc3, 0xc7, 0xcb, 0xda, 0xe6, 0x12, 0xa5, 0x0c, 0xc7, 0x21, 0xa6, 0x62, + 0xbd, 0xc3, 0x0b, 0x46, 0xfe, 0x43, 0x9a, 0x1a, 0x3c, 0x73, 0x0b, 0x23, + 0xb2, 0x7c, 0xa7, 0xae, 0x65, 0x18, 0x55, 0xe3, 0xb8, 0x7b, 0x94, 0xbc, + 0x16, 0x93, 0x5e, 0xda, 0x40, 0x91, 0x4f, 0x29, 0x75, 0xe3, 0xbc, 0x72, + 0xb3, 0xb1, 0xfd, 0x2f, 0x08, 0xd8, 0xa7, 0x00, 0xdc, 0xf1, 0xc6, 0x56, + 0x8e, 0xdd, 0xcb, 0xee, 0x77, 0x21, 0x68, 0x34, 0x8b, 0x1b, 0xd2, 0x8b, + 0xf5, 0x68, 0x12, 0x7c, 0xa7, 0xed, 0xba, 0x9d, 0x12, 0xe2, 0x55, 0x8f, + 0x54, 0x7d, 0xbe, 0xa7, 0x76, 0x9d, 0xa9, 0x21, 0xb0, }; -static const unsigned kPreloadedHSTSBits = 117858; +static const unsigned kPreloadedHSTSBits = 118534; -static const unsigned kHSTSRootPosition = 117270; +static const unsigned kHSTSRootPosition = 117945; #endif // NET_HTTP_TRANSPORT_SECURITY_STATE_STATIC_H_
diff --git a/net/http/transport_security_state_static.json b/net/http/transport_security_state_static.json index d5dbad1..288797f 100644 --- a/net/http/transport_security_state_static.json +++ b/net/http/transport_security_state_static.json
@@ -1367,7 +1367,6 @@ { "name": "onedot.nl", "include_subdomains": true, "mode": "force-https" }, { "name": "powerplannerapp.com", "include_subdomains": true, "mode": "force-https" }, { "name": "ru-sprachstudio.ch", "include_subdomains": true, "mode": "force-https" }, - { "name": "segu-info.com.ar", "include_subdomains": true, "mode": "force-https" }, { "name": "slattery.co", "include_subdomains": true, "mode": "force-https" }, { "name": "slidebatch.com", "include_subdomains": true, "mode": "force-https" }, { "name": "smartship.co.jp", "include_subdomains": true, "mode": "force-https" }, @@ -1775,7 +1774,20 @@ { "name": "whd-guide.de", "include_subdomains": true, "mode": "force-https" }, { "name": "whocalld.com", "include_subdomains": true, "mode": "force-https" }, { "name": "wootton95.com", "include_subdomains": true, "mode": "force-https" }, - { "name": "fassadenverkleidung24.de", "include_subdomains": true, "mode": "force-https" } + { "name": "fassadenverkleidung24.de", "include_subdomains": true, "mode": "force-https" }, + { "name": "uspsoig.gov", "include_subdomains": true, "mode": "force-https" }, + { "name": "notalone.gov", "include_subdomains": true, "mode": "force-https" }, + { "name": "aids.gov", "include_subdomains": true, "mode": "force-https" }, + { "name": "itdashboard.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "paymentaccuracy.gov", "include_subdomains": true, "mode": "force-https" }, + { "name": "cao.gov", "include_subdomains": true, "mode": "force-https" }, + { "name": "cfo.gov", "include_subdomains": true, "mode": "force-https" }, + { "name": "cio.gov", "include_subdomains": true, "mode": "force-https" }, + { "name": "earmarks.gov", "include_subdomains": true, "mode": "force-https" }, + { "name": "bfelob.gov", "include_subdomains": true, "mode": "force-https" }, + { "name": "max.gov", "include_subdomains": true, "mode": "force-https" }, + { "name": "save.gov", "include_subdomains": true, "mode": "force-https" }, + { "name": "saveaward.gov", "include_subdomains": true, "mode": "force-https" } ], // |ReportUMAOnPinFailure| uses these to report which domain was associated
diff --git a/net/http/transport_security_state_unittest.cc b/net/http/transport_security_state_unittest.cc index 44fc2d6..2e734087 100644 --- a/net/http/transport_security_state_unittest.cc +++ b/net/http/transport_security_state_unittest.cc
@@ -786,7 +786,7 @@ TEST_F(TransportSecurityStateTest, PinValidationWithoutRejectedCerts) { // kGoodPath is blog.torproject.org. - static const char* kGoodPath[] = { + static const char* const kGoodPath[] = { "sha1/m9lHYJYke9k0GtVZ+bXSQYE8nDI=", "sha1/o5OZxATDsgmwgcIfIWIneMJ0jkw=", "sha1/wHqYaI2J+6sFZAwRfap9ZbjKzE4=", @@ -795,7 +795,7 @@ // kBadPath is plus.google.com via Trustcenter, which is utterly wrong for // torproject.org. - static const char* kBadPath[] = { + static const char* const kBadPath[] = { "sha1/4BjDjn8v2lWeUFQnqSs0BgbIcrU=", "sha1/gzuEEAB/bkqdQS3EIjk2by7lW+k=", "sha1/SOZo+SvSspXXR9gjIBBPM5iQn9Q=",
diff --git a/net/http/url_security_manager_unittest.cc b/net/http/url_security_manager_unittest.cc index cf072e5..8e6d8c5 100644 --- a/net/http/url_security_manager_unittest.cc +++ b/net/http/url_security_manager_unittest.cc
@@ -15,12 +15,12 @@ namespace { struct TestData { - const char* url; + const char* const url; bool succeds_in_windows_default; bool succeeds_in_whitelist; }; -const char* kTestAuthWhitelist = "*example.com,*foobar.com,baz"; +const char kTestAuthWhitelist[] = "*example.com,*foobar.com,baz"; // Under Windows the following will be allowed by default: // localhost
diff --git a/net/net.gypi b/net/net.gypi index 6da22e3..5b5a5f9 100644 --- a/net/net.gypi +++ b/net/net.gypi
@@ -1718,6 +1718,7 @@ 'websockets/websocket_deflate_predictor_impl_test.cc', 'websockets/websocket_deflate_stream_test.cc', 'websockets/websocket_deflater_test.cc', + 'websockets/websocket_end_to_end_test.cc', 'websockets/websocket_errors_test.cc', 'websockets/websocket_extension_parser_test.cc', 'websockets/websocket_frame_parser_test.cc',
diff --git a/net/proxy/dhcp_proxy_script_adapter_fetcher_win_unittest.cc b/net/proxy/dhcp_proxy_script_adapter_fetcher_win_unittest.cc index dc0d1b4f..af858d63 100644 --- a/net/proxy/dhcp_proxy_script_adapter_fetcher_win_unittest.cc +++ b/net/proxy/dhcp_proxy_script_adapter_fetcher_win_unittest.cc
@@ -21,7 +21,7 @@ namespace { -const char* const kPacUrl = "http://pacserver/script.pac"; +const char kPacUrl[] = "http://pacserver/script.pac"; // In net/proxy/dhcp_proxy_script_fetcher_win_unittest.cc there are a few // tests that exercise DhcpProxyScriptAdapterFetcher end-to-end along with
diff --git a/net/proxy/proxy_config_source.cc b/net/proxy/proxy_config_source.cc index 80e2735..f3137ff 100644 --- a/net/proxy/proxy_config_source.cc +++ b/net/proxy/proxy_config_source.cc
@@ -11,7 +11,7 @@ namespace { -const char* kSourceNames[] = { +const char* const kSourceNames[] = { "UNKNOWN", "SYSTEM", "SYSTEM FAILED",
diff --git a/net/proxy/proxy_server_unittest.cc b/net/proxy/proxy_server_unittest.cc index 2471b59..0a596e47 100644 --- a/net/proxy/proxy_server_unittest.cc +++ b/net/proxy/proxy_server_unittest.cc
@@ -11,12 +11,12 @@ // was labelled correctly, and the accessors all give the right data. TEST(ProxyServerTest, FromURI) { const struct { - const char* input_uri; - const char* expected_uri; + const char* const input_uri; + const char* const expected_uri; net::ProxyServer::Scheme expected_scheme; - const char* expected_host; + const char* const expected_host; int expected_port; - const char* expected_pac_string; + const char* const expected_pac_string; } tests[] = { // HTTP proxy URIs: { @@ -191,7 +191,7 @@ // Test parsing some invalid inputs. TEST(ProxyServerTest, Invalid) { - const char* tests[] = { + const char* const tests[] = { "", " ", "dddf:", // not a valid port @@ -214,7 +214,7 @@ // Test that LWS (SP | HT) is disregarded from the ends. TEST(ProxyServerTest, Whitespace) { - const char* tests[] = { + const char* const tests[] = { " foopy:80", "foopy:80 \t", " \tfoopy:80 ", @@ -230,8 +230,8 @@ // Test parsing a ProxyServer from a PAC representation. TEST(ProxyServerTest, FromPACString) { const struct { - const char* input_pac; - const char* expected_uri; + const char* const input_pac; + const char* const expected_uri; } tests[] = { { "PROXY foopy:10", @@ -288,7 +288,7 @@ // Test parsing a ProxyServer from an invalid PAC representation. TEST(ProxyServerTest, FromPACStringInvalid) { - const char* tests[] = { + const char* const tests[] = { "PROXY", // missing host/port. "HTTPS", // missing host/port. "SOCKS", // missing host/port. @@ -304,8 +304,8 @@ TEST(ProxyServerTest, ComparatorAndEquality) { struct { // Inputs. - const char* server1; - const char* server2; + const char* const server1; + const char* const server2; // Expectation. // -1 means server1 is less than server2
diff --git a/net/proxy/proxy_service.cc b/net/proxy/proxy_service.cc index 9d5a0b0..a62732d 100644 --- a/net/proxy/proxy_service.cc +++ b/net/proxy/proxy_service.cc
@@ -301,12 +301,11 @@ class UnsetProxyConfigService : public ProxyConfigService { public: UnsetProxyConfigService() {} - virtual ~UnsetProxyConfigService() {} + ~UnsetProxyConfigService() override {} - virtual void AddObserver(Observer* observer) override {} - virtual void RemoveObserver(Observer* observer) override {} - virtual ConfigAvailability GetLatestProxyConfig( - ProxyConfig* config) override { + void AddObserver(Observer* observer) override {} + void RemoveObserver(Observer* observer) override {} + ConfigAvailability GetLatestProxyConfig(ProxyConfig* config) override { return CONFIG_UNSET; } };
diff --git a/net/quic/crypto/aead_base_decrypter.h b/net/quic/crypto/aead_base_decrypter.h index 5118b11..1aeb6713 100644 --- a/net/quic/crypto/aead_base_decrypter.h +++ b/net/quic/crypto/aead_base_decrypter.h
@@ -42,11 +42,6 @@ // QuicDecrypter implementation bool SetKey(base::StringPiece key) override; bool SetNoncePrefix(base::StringPiece nonce_prefix) override; - bool Decrypt(base::StringPiece nonce, - base::StringPiece associated_data, - base::StringPiece ciphertext, - unsigned char* output, - size_t* output_length) override; QuicData* DecryptPacket(QuicPacketSequenceNumber sequence_number, base::StringPiece associated_data, base::StringPiece ciphertext) override; @@ -80,6 +75,12 @@ #endif // !defined(USE_OPENSSL) private: + bool Decrypt(base::StringPiece nonce, + base::StringPiece associated_data, + base::StringPiece ciphertext, + unsigned char* output, + size_t* output_length); + #if defined(USE_OPENSSL) const EVP_AEAD* const aead_alg_; #else
diff --git a/net/quic/crypto/aes_128_gcm_12_decrypter_test.cc b/net/quic/crypto/aes_128_gcm_12_decrypter_test.cc index 037bf7e..377d2b5 100644 --- a/net/quic/crypto/aes_128_gcm_12_decrypter_test.cc +++ b/net/quic/crypto/aes_128_gcm_12_decrypter_test.cc
@@ -257,15 +257,13 @@ StringPiece nonce, StringPiece associated_data, StringPiece ciphertext) { - size_t plaintext_size = ciphertext.length(); - scoped_ptr<char[]> plaintext(new char[plaintext_size]); - - if (!decrypter->Decrypt(nonce, associated_data, ciphertext, - reinterpret_cast<unsigned char*>(plaintext.get()), - &plaintext_size)) { - return nullptr; - } - return new QuicData(plaintext.release(), plaintext_size, true); + QuicPacketSequenceNumber sequence_number; + StringPiece nonce_prefix(nonce.data(), + nonce.size() - sizeof(sequence_number)); + decrypter->SetNoncePrefix(nonce_prefix); + memcpy(&sequence_number, nonce.data() + nonce_prefix.size(), + sizeof(sequence_number)); + return decrypter->DecryptPacket(sequence_number, associated_data, ciphertext); } TEST(Aes128Gcm12DecrypterTest, Decrypt) {
diff --git a/net/quic/crypto/chacha20_poly1305_decrypter_test.cc b/net/quic/crypto/chacha20_poly1305_decrypter_test.cc index 312e2d4..54ca9ff4 100644 --- a/net/quic/crypto/chacha20_poly1305_decrypter_test.cc +++ b/net/quic/crypto/chacha20_poly1305_decrypter_test.cc
@@ -75,15 +75,13 @@ StringPiece nonce, StringPiece associated_data, StringPiece ciphertext) { - size_t plaintext_size = ciphertext.length(); - scoped_ptr<char[]> plaintext(new char[plaintext_size]); - - if (!decrypter->Decrypt(nonce, associated_data, ciphertext, - reinterpret_cast<unsigned char*>(plaintext.get()), - &plaintext_size)) { - return nullptr; - } - return new QuicData(plaintext.release(), plaintext_size, true); + QuicPacketSequenceNumber sequence_number; + StringPiece nonce_prefix(nonce.data(), + nonce.size() - sizeof(sequence_number)); + decrypter->SetNoncePrefix(nonce_prefix); + memcpy(&sequence_number, nonce.data() + nonce_prefix.size(), + sizeof(sequence_number)); + return decrypter->DecryptPacket(sequence_number, associated_data, ciphertext); } TEST(ChaCha20Poly1305DecrypterTest, Decrypt) {
diff --git a/net/quic/crypto/crypto_protocol.h b/net/quic/crypto/crypto_protocol.h index 9a7f6c6..ae7e78d 100644 --- a/net/quic/crypto/crypto_protocol.h +++ b/net/quic/crypto/crypto_protocol.h
@@ -58,6 +58,7 @@ const QuicTag k1CON = TAG('1', 'C', 'O', 'N'); // Emulate a single connection const QuicTag kNTLP = TAG('N', 'T', 'L', 'P'); // No tail loss probe const QuicTag kNCON = TAG('N', 'C', 'O', 'N'); // N Connection Congestion Ctrl +const QuicTag kNRTO = TAG('N', 'R', 'T', 'O'); // CWND reduction on loss // Loss detection algorithm types const QuicTag kNACK = TAG('N', 'A', 'C', 'K'); // TCP style nack counting
diff --git a/net/quic/crypto/crypto_secret_boxer.cc b/net/quic/crypto/crypto_secret_boxer.cc index 5d8a11b..445d888 100644 --- a/net/quic/crypto/crypto_secret_boxer.cc +++ b/net/quic/crypto/crypto_secret_boxer.cc
@@ -74,26 +74,29 @@ return false; } - char nonce[kBoxNonceSize]; - memcpy(nonce, ciphertext.data(), kBoxNonceSize); + StringPiece nonce(ciphertext.data(), kBoxNonceSize); ciphertext.remove_prefix(kBoxNonceSize); - - size_t len = ciphertext.size(); - out_storage->resize(len); - char* data = const_cast<char*>(out_storage->data()); + QuicPacketSequenceNumber sequence_number; + StringPiece nonce_prefix(nonce.data(), + nonce.size() - sizeof(sequence_number)); + memcpy(&sequence_number, nonce.data() + nonce_prefix.size(), + sizeof(sequence_number)); scoped_ptr<QuicDecrypter> decrypter(QuicDecrypter::Create(kAESG)); if (!decrypter->SetKey(key_)) { DLOG(DFATAL) << "CryptoSecretBoxer's decrypter->SetKey failed."; return false; } - if (!decrypter->Decrypt(StringPiece(nonce, kBoxNonceSize), StringPiece(), - ciphertext, reinterpret_cast<unsigned char*>(data), - &len)) { + decrypter->SetNoncePrefix(nonce_prefix); + scoped_ptr<QuicData> decrypted( + decrypter->DecryptPacket(sequence_number, StringPiece(), ciphertext)); + if (!decrypted.get()) { return false; } - out->set(data, len); + out_storage->resize(decrypted->length()); + out_storage->assign(decrypted->data(), decrypted->length()); + out->set(out_storage->data(), decrypted->length()); return true; }
diff --git a/net/quic/crypto/crypto_server_test.cc b/net/quic/crypto/crypto_server_test.cc index bd78850..b140e23 100644 --- a/net/quic/crypto/crypto_server_test.cc +++ b/net/quic/crypto/crypto_server_test.cc
@@ -302,7 +302,7 @@ ::testing::ValuesIn(GetTestParams())); TEST_P(CryptoServerTest, BadSNI) { - static const char* kBadSNIs[] = { + static const char* const kBadSNIs[] = { "", "foo", "#00", @@ -368,7 +368,7 @@ TEST_P(CryptoServerTest, BadSourceAddressToken) { // Invalid source-address tokens should be ignored. - static const char* kBadSourceAddressTokens[] = { + static const char* const kBadSourceAddressTokens[] = { "", "foo", "#0000", @@ -390,7 +390,7 @@ TEST_P(CryptoServerTest, BadClientNonce) { // Invalid nonces should be ignored. - static const char* kBadNonces[] = { + static const char* const kBadNonces[] = { "", "#0000", "#0000000000000000000000000000000000000000",
diff --git a/net/quic/crypto/null_decrypter.cc b/net/quic/crypto/null_decrypter.cc index 77aee4c..4411b7c0 100644 --- a/net/quic/crypto/null_decrypter.cc +++ b/net/quic/crypto/null_decrypter.cc
@@ -19,31 +19,6 @@ return nonce_prefix.empty(); } -bool NullDecrypter::Decrypt(StringPiece /*nonce*/, - StringPiece associated_data, - StringPiece ciphertext, - unsigned char* output, - size_t* output_length) { - QuicDataReader reader(ciphertext.data(), ciphertext.length()); - - uint128 hash; - if (!ReadHash(&reader, &hash)) { - return false; - } - - StringPiece plaintext = reader.ReadRemainingPayload(); - - // TODO(rch): avoid buffer copy here - string buffer = associated_data.as_string(); - plaintext.AppendToString(&buffer); - if (hash != ComputeHash(buffer)) { - return false; - } - memcpy(output, plaintext.data(), plaintext.length()); - *output_length = plaintext.length(); - return true; -} - QuicData* NullDecrypter::DecryptPacket(QuicPacketSequenceNumber /*seq_number*/, StringPiece associated_data, StringPiece ciphertext) {
diff --git a/net/quic/crypto/null_decrypter.h b/net/quic/crypto/null_decrypter.h index 6f23290..db98a99 100644 --- a/net/quic/crypto/null_decrypter.h +++ b/net/quic/crypto/null_decrypter.h
@@ -24,11 +24,6 @@ // QuicDecrypter implementation bool SetKey(base::StringPiece key) override; bool SetNoncePrefix(base::StringPiece nonce_prefix) override; - bool Decrypt(base::StringPiece nonce, - base::StringPiece associated_data, - base::StringPiece ciphertext, - unsigned char* output, - size_t* output_length) override; QuicData* DecryptPacket(QuicPacketSequenceNumber sequence_number, base::StringPiece associated_data, base::StringPiece ciphertext) override;
diff --git a/net/quic/crypto/proof_verifier_chromium.cc b/net/quic/crypto/proof_verifier_chromium.cc index f9568c2..fb903b6c 100644 --- a/net/quic/crypto/proof_verifier_chromium.cc +++ b/net/quic/crypto/proof_verifier_chromium.cc
@@ -10,6 +10,7 @@ #include "base/compiler_specific.h" #include "base/logging.h" #include "base/metrics/histogram.h" +#include "base/profiler/scoped_tracker.h" #include "base/stl_util.h" #include "base/strings/stringprintf.h" #include "crypto/signature_verifier.h" @@ -120,6 +121,11 @@ std::string* error_details, scoped_ptr<ProofVerifyDetails>* verify_details, ProofVerifierCallback* callback) { + // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "422516 ProofVerifierChromium::Job::VerifyProof")); + DCHECK(error_details); DCHECK(verify_details); DCHECK(callback); @@ -234,6 +240,11 @@ } int ProofVerifierChromium::Job::DoVerifyCertComplete(int result) { + // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "422516 ProofVerifierChromium::Job::DoVerifyCertComplete")); + verifier_.reset(); const CertVerifyResult& cert_verify_result = @@ -278,6 +289,11 @@ bool ProofVerifierChromium::Job::VerifySignature(const string& signed_data, const string& signature, const string& cert) { + // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "422516 ProofVerifierChromium::Job::VerifySignature")); + StringPiece spki; if (!asn1::ExtractSPKIFromDERCert(cert, &spki)) { DLOG(WARNING) << "ExtractSPKIFromDERCert failed"; @@ -371,6 +387,11 @@ std::string* error_details, scoped_ptr<ProofVerifyDetails>* verify_details, ProofVerifierCallback* callback) { + // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "422516 ProofVerifierChromium::VerifyProof")); + if (!verify_context) { *error_details = "Missing context"; return QUIC_FAILURE;
diff --git a/net/quic/crypto/quic_crypto_client_config.cc b/net/quic/crypto/quic_crypto_client_config.cc index 9f7f0da7..1e12424 100644 --- a/net/quic/crypto/quic_crypto_client_config.cc +++ b/net/quic/crypto/quic_crypto_client_config.cc
@@ -6,6 +6,7 @@ #include "base/metrics/histogram.h" #include "base/metrics/sparse_histogram.h" +#include "base/profiler/scoped_tracker.h" #include "base/stl_util.h" #include "base/strings/string_util.h" #include "net/quic/crypto/cert_compressor.h" @@ -344,6 +345,11 @@ const CachedState* cached, QuicCryptoNegotiatedParameters* out_params, CryptoHandshakeMessage* out) const { + // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "422516 QuicCryptoClientConfig::FillInchoateClientHello")); + out->set_tag(kCHLO); out->set_minimum_size(kClientHelloMinimumSize); @@ -402,6 +408,11 @@ QuicCryptoNegotiatedParameters* out_params, CryptoHandshakeMessage* out, string* error_details) const { + // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "422516 QuicCryptoClientConfig::FillClientHello")); + DCHECK(error_details != nullptr); FillInchoateClientHello(server_id, preferred_version, cached,
diff --git a/net/quic/crypto/quic_decrypter.h b/net/quic/crypto/quic_decrypter.h index 06c76370..9e6e1d2 100644 --- a/net/quic/crypto/quic_decrypter.h +++ b/net/quic/crypto/quic_decrypter.h
@@ -39,18 +39,6 @@ // packet sequence number, even when retransmitting a lost packet. virtual bool SetNoncePrefix(base::StringPiece nonce_prefix) = 0; - // Decrypt authenticates |associated_data| and |ciphertext| and then decrypts - // |ciphertext| into |output|, using |nonce|. |nonce| must be 8 bytes longer - // than the nonce prefix length returned by GetNoncePrefixSize() (of the - // encrypter). |output| must be as long as |ciphertext| on entry and, on - // successful return, the true length of the plaintext will be written to - // |*output_length|. - virtual bool Decrypt(base::StringPiece nonce, - base::StringPiece associated_data, - base::StringPiece ciphertext, - unsigned char* output, - size_t* output_length) = 0; - // Returns a newly created QuicData object containing the decrypted // |ciphertext| or nullptr if there is an error. |sequence_number| is // appended to the |nonce_prefix| value provided in SetNoncePrefix()
diff --git a/net/quic/quic_ack_notifier.cc b/net/quic/quic_ack_notifier.cc index 1780985..b399a61b 100644 --- a/net/quic/quic_ack_notifier.cc +++ b/net/quic/quic_ack_notifier.cc
@@ -14,19 +14,13 @@ namespace net { -QuicAckNotifier::PacketInfo::PacketInfo() : packet_payload_size(0) { -} - -QuicAckNotifier::PacketInfo::PacketInfo(int payload_size) - : packet_payload_size(payload_size) { -} - QuicAckNotifier::DelegateInterface::DelegateInterface() {} QuicAckNotifier::DelegateInterface::~DelegateInterface() {} QuicAckNotifier::QuicAckNotifier(DelegateInterface* delegate) : delegate_(delegate), + unacked_packets_(0), retransmitted_packet_count_(0), retransmitted_byte_count_(0) { DCHECK(delegate); @@ -38,16 +32,17 @@ void QuicAckNotifier::AddSequenceNumber( const QuicPacketSequenceNumber& sequence_number, int packet_payload_size) { - sequence_numbers_.insert(make_pair(sequence_number, - PacketInfo(packet_payload_size))); - + ++unacked_packets_; DVLOG(1) << "AckNotifier waiting for packet: " << sequence_number; } bool QuicAckNotifier::OnAck(QuicPacketSequenceNumber sequence_number, QuicTime::Delta delta_largest_observed) { - DCHECK(ContainsKey(sequence_numbers_, sequence_number)); - sequence_numbers_.erase(sequence_number); + if (unacked_packets_ <= 0) { + LOG(DFATAL) << "Acked more packets than were tracked."; + return true; + } + --unacked_packets_; if (IsEmpty()) { // We have seen all the sequence numbers we were waiting for, trigger // callback notification. @@ -59,26 +54,9 @@ return false; } -void QuicAckNotifier::UpdateSequenceNumber( - QuicPacketSequenceNumber old_sequence_number, - QuicPacketSequenceNumber new_sequence_number) { - DCHECK(!ContainsKey(sequence_numbers_, new_sequence_number)); - - PacketInfo packet_info; - auto it = sequence_numbers_.find(old_sequence_number); - if (it != sequence_numbers_.end()) { - packet_info = it->second; - sequence_numbers_.erase(it); - } else { - DLOG(DFATAL) << "Old sequence number not found."; - } - +void QuicAckNotifier::OnPacketRetransmitted(int packet_payload_size) { ++retransmitted_packet_count_; - retransmitted_byte_count_ += packet_info.packet_payload_size; - sequence_numbers_.insert(make_pair(new_sequence_number, packet_info)); - - DVLOG(1) << "AckNotifier waiting for packet: " << new_sequence_number - << " (retransmitted " << old_sequence_number << ")."; + retransmitted_byte_count_ += packet_payload_size; } }; // namespace net
diff --git a/net/quic/quic_ack_notifier.h b/net/quic/quic_ack_notifier.h index f8d813e..160108e 100644 --- a/net/quic/quic_ack_notifier.h +++ b/net/quic/quic_ack_notifier.h
@@ -55,30 +55,20 @@ bool OnAck(QuicPacketSequenceNumber sequence_number, QuicTime::Delta delta_largest_observed); - bool IsEmpty() { return sequence_numbers_.empty(); } + bool IsEmpty() { return unacked_packets_ == 0; } - // If a packet is retransmitted by the connection it will be sent with a - // different sequence number. Updates our internal set of sequence_numbers to - // track the latest number. - void UpdateSequenceNumber(QuicPacketSequenceNumber old_sequence_number, - QuicPacketSequenceNumber new_sequence_number); + // If a packet is retransmitted by the connection, it will be sent with a + // different sequence number. + void OnPacketRetransmitted(int packet_payload_size); private: - struct PacketInfo { - PacketInfo(); - explicit PacketInfo(int payload_size); - - int packet_payload_size; - }; - // The delegate's OnAckNotification() method will be called once we have been // notified of ACKs for all the sequence numbers we are tracking. // This is not owned by OnAckNotifier and must outlive it. scoped_refptr<DelegateInterface> delegate_; - // Sequence numbers this notifier is waiting to hear about. The - // delegate will not be called until this is empty. - base::hash_map<QuicPacketSequenceNumber, PacketInfo> sequence_numbers_; + // The number of unacked packets being tracked. + int unacked_packets_; // Number of packets that had to be retransmitted. int retransmitted_packet_count_; @@ -88,6 +78,6 @@ DISALLOW_COPY_AND_ASSIGN(QuicAckNotifier); }; -}; // namespace net +} // namespace net #endif // NET_QUIC_QUIC_ACK_NOTIFIER_H_
diff --git a/net/quic/quic_ack_notifier_manager.cc b/net/quic/quic_ack_notifier_manager.cc index 129a951e..0d37752 100644 --- a/net/quic/quic_ack_notifier_manager.cc +++ b/net/quic/quic_ack_notifier_manager.cc
@@ -34,8 +34,8 @@ // One or more AckNotifiers are registered as interested in this sequence // number. Iterate through them and call OnAck on each. - AckNotifierSet& ack_notifier_set = map_it->second; - for (QuicAckNotifier* ack_notifier : ack_notifier_set) { + AckNotifierList& ack_notifier_list = map_it->second; + for (QuicAckNotifier* ack_notifier : ack_notifier_list) { ack_notifier->OnAck(sequence_number, delta_largest_observed); // If this has resulted in an empty AckNotifer, erase it. @@ -50,9 +50,10 @@ ack_notifier_map_.erase(map_it); } -void AckNotifierManager::UpdateSequenceNumber( +void AckNotifierManager::OnPacketRetransmitted( QuicPacketSequenceNumber old_sequence_number, - QuicPacketSequenceNumber new_sequence_number) { + QuicPacketSequenceNumber new_sequence_number, + int packet_payload_size) { auto map_it = ack_notifier_map_.find(old_sequence_number); if (map_it == ack_notifier_map_.end()) { // No AckNotifiers are interested in the old sequence number. @@ -60,15 +61,14 @@ } // Update the existing QuicAckNotifiers to the new sequence number. - AckNotifierSet& ack_notifier_set = map_it->second; - for (QuicAckNotifier* ack_notifier : ack_notifier_set) { - ack_notifier->UpdateSequenceNumber(old_sequence_number, - new_sequence_number); + AckNotifierList& ack_notifier_list = map_it->second; + for (QuicAckNotifier* ack_notifier : ack_notifier_list) { + ack_notifier->OnPacketRetransmitted(packet_payload_size); } // The old sequence number is no longer of interest, copy the updated // AckNotifiers to the new sequence number before deleting the old. - ack_notifier_map_[new_sequence_number] = ack_notifier_set; + ack_notifier_map_[new_sequence_number] = ack_notifier_list; ack_notifier_map_.erase(map_it); } @@ -86,7 +86,7 @@ // Update the mapping in the other direction, from sequence number to // AckNotifier. - ack_notifier_map_[serialized_packet.sequence_number].insert(notifier); + ack_notifier_map_[serialized_packet.sequence_number].push_back(notifier); // Take ownership of the AckNotifier. ack_notifiers_.insert(notifier); @@ -112,7 +112,7 @@ // Update the mapping in the other direction, from sequence number to // AckNotifier. - ack_notifier_map_[serialized_packet.sequence_number].insert(notifier); + ack_notifier_map_[serialized_packet.sequence_number].push_back(notifier); // Take ownership of the AckNotifier. ack_notifiers_.insert(notifier);
diff --git a/net/quic/quic_ack_notifier_manager.h b/net/quic/quic_ack_notifier_manager.h index 122bda1..bf4d574 100644 --- a/net/quic/quic_ack_notifier_manager.h +++ b/net/quic/quic_ack_notifier_manager.h
@@ -5,6 +5,7 @@ #ifndef NET_QUIC_QUIC_ACK_NOTIFIER_MANAGER_H_ #define NET_QUIC_QUIC_ACK_NOTIFIER_MANAGER_H_ +#include <list> #include <map> #include "base/containers/hash_tables.h" @@ -34,8 +35,9 @@ // If a packet has been retransmitted with a new sequence number, then this // will be called. It updates the mapping in ack_notifier_map_, and also // updates the internal set of sequence numbers in each matching AckNotifier. - void UpdateSequenceNumber(QuicPacketSequenceNumber old_sequence_number, - QuicPacketSequenceNumber new_sequence_number); + void OnPacketRetransmitted(QuicPacketSequenceNumber old_sequence_number, + QuicPacketSequenceNumber new_sequence_number, + int packet_payload_size); // This is called after a packet has been serialized, is ready to be sent, and // contains retransmittable frames (which may have associated AckNotifiers). @@ -45,8 +47,11 @@ void OnSerializedPacket(const SerializedPacket& serialized_packet); private: + typedef std::list<QuicAckNotifier*> AckNotifierList; typedef base::hash_set<QuicAckNotifier*> AckNotifierSet; - typedef std::map<QuicPacketSequenceNumber, AckNotifierSet> AckNotifierMap; + // TODO(ianswett): Further improvement may come from changing this to a deque. + typedef base::hash_map<QuicPacketSequenceNumber, AckNotifierList> + AckNotifierMap; // On every ACK frame received by the connection, all the ack_notifiers_ will // be told which sequeunce numbers were ACKed.
diff --git a/net/quic/quic_ack_notifier_test.cc b/net/quic/quic_ack_notifier_test.cc index 4e15b98..21c876665 100644 --- a/net/quic/quic_ack_notifier_test.cc +++ b/net/quic/quic_ack_notifier_test.cc
@@ -52,8 +52,8 @@ // new sequeunce numbers. TEST_F(QuicAckNotifierTest, UpdateSeqNums) { // Update a couple of the sequence numbers (i.e. retransmitted packets) - notifier_->UpdateSequenceNumber(99, 3000); - notifier_->UpdateSequenceNumber(1234, 3001); + notifier_->OnPacketRetransmitted(20); + notifier_->OnPacketRetransmitted(3); EXPECT_CALL(*delegate_, OnAckNotification(2, 20 + 3, _)).Times(1); EXPECT_FALSE(notifier_->OnAck(26, zero_)); // original
diff --git a/net/quic/quic_client_session.cc b/net/quic/quic_client_session.cc index 1ea88270..1b59a40 100644 --- a/net/quic/quic_client_session.cc +++ b/net/quic/quic_client_session.cc
@@ -8,6 +8,7 @@ #include "base/message_loop/message_loop.h" #include "base/metrics/histogram.h" #include "base/metrics/sparse_histogram.h" +#include "base/profiler/scoped_tracker.h" #include "base/stl_util.h" #include "base/strings/string_number_conversions.h" #include "base/values.h" @@ -175,6 +176,11 @@ num_packets_read_(0), going_away_(false), weak_factory_(this) { + // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "422516 QuicClientSession::QuicClientSession")); + connection->set_debug_visitor(logger_); IPEndPoint address; if (socket && socket->GetLocalAddress(&address) == OK &&
diff --git a/net/quic/quic_connection_test.cc b/net/quic/quic_connection_test.cc index 7622f04a..091dc9ec 100644 --- a/net/quic/quic_connection_test.cc +++ b/net/quic/quic_connection_test.cc
@@ -144,22 +144,6 @@ bool SetNoncePrefix(StringPiece nonce_prefix) override { return true; } - bool Decrypt(StringPiece nonce, - StringPiece associated_data, - StringPiece ciphertext, - unsigned char* output, - size_t* output_length) override { - if (ciphertext.size() < kTagSize) { - return false; - } - if (!CheckTag(ciphertext, GetTag(ciphertext))) { - return false; - } - *output_length = ciphertext.size() - kTagSize; - memcpy(output, ciphertext.data(), *output_length); - return true; - } - QuicData* DecryptPacket(QuicPacketSequenceNumber sequence_number, StringPiece associated_data, StringPiece ciphertext) override {
diff --git a/net/quic/quic_crypto_client_stream.cc b/net/quic/quic_crypto_client_stream.cc index fec38b5..26bd1717 100644 --- a/net/quic/quic_crypto_client_stream.cc +++ b/net/quic/quic_crypto_client_stream.cc
@@ -254,9 +254,9 @@ const CryptoHandshakeMessage* in, QuicCryptoClientConfig::CachedState* cached) { // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed. - tracked_objects::ScopedTracker tracking_profile( + tracked_objects::ScopedTracker tracking_profile1( FROM_HERE_WITH_EXPLICIT_FUNCTION( - "422516 QuicCryptoClientStream::DoSendCHLO")); + "422516 QuicCryptoClientStream::DoSendCHLO1")); // Send the client hello in plaintext. session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_NONE); @@ -307,6 +307,12 @@ &crypto_negotiated_params_, &out, &error_details); + + // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed. + tracked_objects::ScopedTracker tracking_profile2( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "422516 QuicCryptoClientStream::DoSendCHLO2")); + if (error != QUIC_NO_ERROR) { // Flush the cached config so that, if it's bad, the server has a // chance to send us another in the future. @@ -439,7 +445,7 @@ if (!verify_ok_) { next_state_ = STATE_NONE; - if (verify_details_) { + if (verify_details_.get()) { client_session()->OnProofVerifyDetailsAvailable(*verify_details_); } UMA_HISTOGRAM_BOOLEAN("Net.QuicVerifyProofFailed.HandshakeConfirmed",
diff --git a/net/quic/quic_fec_group_test.cc b/net/quic/quic_fec_group_test.cc index b9420dd..a918aeb 100644 --- a/net/quic/quic_fec_group_test.cc +++ b/net/quic/quic_fec_group_test.cc
@@ -19,7 +19,7 @@ namespace { -const char* kData[] = { +const char* const kData[] = { "abc12345678", "987defg", "ghi12345",
diff --git a/net/quic/quic_framer_test.cc b/net/quic/quic_framer_test.cc index bb852a0..0fa4ce9 100644 --- a/net/quic/quic_framer_test.cc +++ b/net/quic/quic_framer_test.cc
@@ -141,14 +141,6 @@ ~TestDecrypter() override {} bool SetKey(StringPiece key) override { return true; } bool SetNoncePrefix(StringPiece nonce_prefix) override { return true; } - bool Decrypt(StringPiece nonce, - StringPiece associated_data, - StringPiece ciphertext, - unsigned char* output, - size_t* output_length) override { - CHECK(false) << "Not implemented"; - return false; - } QuicData* DecryptPacket(QuicPacketSequenceNumber sequence_number, StringPiece associated_data, StringPiece ciphertext) override {
diff --git a/net/quic/quic_http_stream.cc b/net/quic/quic_http_stream.cc index 4f8e4e4b..b22fb93 100644 --- a/net/quic/quic_http_stream.cc +++ b/net/quic/quic_http_stream.cc
@@ -108,7 +108,18 @@ CHECK(!callback.is_null()); CHECK(response); - if (!stream_) { + // TODO(rch): remove this once we figure out why channel ID is not being + // sent when it should be. + HostPortPair origin = HostPortPair::FromURL(request_info_->url); + if (origin.Equals(HostPortPair("accounts.google.com", 443))) { + SSLInfo ssl_info; + bool secure_session = + session_->GetSSLInfo(&ssl_info) && ssl_info.cert.get(); + DCHECK(secure_session); + UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.CookieSentToAccountsOverChannelId", + ssl_info.channel_id_sent); + } + if (!stream_) { return ERR_CONNECTION_CLOSED; }
diff --git a/net/quic/quic_packet_generator.cc b/net/quic/quic_packet_generator.cc index 22bf530..bfecf5d 100644 --- a/net/quic/quic_packet_generator.cc +++ b/net/quic/quic_packet_generator.cc
@@ -177,7 +177,7 @@ // We want to track which packet this stream frame ends up in. if (FLAGS_quic_attach_ack_notifiers_to_packets) { if (notifier != nullptr) { - ack_notifiers_.insert(notifier); + ack_notifiers_.push_back(notifier); } } else { frame.stream_frame->notifier = notifier; @@ -227,7 +227,7 @@ // Try to close FEC group since we've either run out of data to send or we're // blocked. If not in batch mode, force close the group. - MaybeSendFecPacketAndCloseGroup(/*flush=*/false); + MaybeSendFecPacketAndCloseGroup(/*force=*/false); DCHECK(InBatchMode() || !packet_creator_.HasPendingFrames()); return QuicConsumedData(total_bytes_consumed, fin_consumed); @@ -317,7 +317,7 @@ // Flush out any pending frames in the generator and the creator, and then // send out FEC packet. SendQueuedFrames(true); - MaybeSendFecPacketAndCloseGroup(/*flush=*/true); + MaybeSendFecPacketAndCloseGroup(/*force=*/true); } QuicTime::Delta QuicPacketGenerator::GetFecTimeout( @@ -407,7 +407,7 @@ } delegate_->OnSerializedPacket(serialized_packet); - MaybeSendFecPacketAndCloseGroup(/*flush=*/false); + MaybeSendFecPacketAndCloseGroup(/*force=*/false); // The packet has now been serialized, safe to delete pending frames. pending_ack_frame_.reset();
diff --git a/net/quic/quic_packet_generator.h b/net/quic/quic_packet_generator.h index a86a746..0da94f0 100644 --- a/net/quic/quic_packet_generator.h +++ b/net/quic/quic_packet_generator.h
@@ -53,6 +53,8 @@ #ifndef NET_QUIC_QUIC_PACKET_GENERATOR_H_ #define NET_QUIC_QUIC_PACKET_GENERATOR_H_ +#include <list> + #include "base/containers/hash_tables.h" #include "net/quic/quic_ack_notifier.h" #include "net/quic/quic_packet_creator.h" @@ -256,7 +258,7 @@ scoped_ptr<QuicStopWaitingFrame> pending_stop_waiting_frame_; // Stores notifiers that should be attached to the next serialized packet. - base::hash_set<QuicAckNotifier*> ack_notifiers_; + std::list<QuicAckNotifier*> ack_notifiers_; DISALLOW_COPY_AND_ASSIGN(QuicPacketGenerator); };
diff --git a/net/quic/quic_protocol.h b/net/quic/quic_protocol.h index d87cb7ed..3daf9174 100644 --- a/net/quic/quic_protocol.h +++ b/net/quic/quic_protocol.h
@@ -1033,7 +1033,7 @@ RetransmittableFrames* retransmittable_frames; // Optional notifiers which will be informed when this packet has been ACKed. - base::hash_set<QuicAckNotifier*> notifiers; + std::list<QuicAckNotifier*> notifiers; }; struct NET_EXPORT_PRIVATE TransmissionInfo {
diff --git a/net/quic/quic_sent_packet_manager.cc b/net/quic/quic_sent_packet_manager.cc index 91775523..34bb972 100644 --- a/net/quic/quic_sent_packet_manager.cc +++ b/net/quic/quic_sent_packet_manager.cc
@@ -100,6 +100,7 @@ pending_timer_transmission_count_(0), max_tail_loss_probes_(kDefaultMaxTailLossProbes), using_pacing_(false), + use_new_rto_(false), handshake_confirmed_(false) { } @@ -154,6 +155,9 @@ if (HasClientSentConnectionOption(config, kNTLP)) { max_tail_loss_probes_ = 0; } + if (HasClientSentConnectionOption(config, kNRTO)) { + use_new_rto_ = true; + } if (config.HasReceivedConnectionOptions() && ContainsQuicTag(config.ReceivedConnectionOptions(), kTIME)) { loss_algorithm_.reset(LossDetectionInterface::Create(kTime)); @@ -215,6 +219,10 @@ HandleAckForSentPackets(ack_frame); InvokeLossDetection(ack_receive_time); + // Ignore losses in RTO mode. + if (FLAGS_quic_use_new_rto && consecutive_rto_count_ > 0 && !use_new_rto_) { + packets_lost_.clear(); + } MaybeInvokeCongestionEvent(rtt_updated, bytes_in_flight); unacked_packets_.RemoveObsoletePackets(); @@ -243,7 +251,9 @@ // a spurious RTO from happening again. rtt_stats_.ExpireSmoothedMetrics(); } else { - send_algorithm_->OnRetransmissionTimeout(true); + if (!use_new_rto_) { + send_algorithm_->OnRetransmissionTimeout(true); + } } } // Reset all retransmit counters any time a new packet is acked. @@ -566,10 +576,10 @@ << "pending_retransmissions_. sequence_number: " << original_sequence_number; } - // A notifier may be waiting to hear about ACKs for the original sequence - // number. Inform them that the sequence number has changed. - ack_notifier_manager_.UpdateSequenceNumber(original_sequence_number, - sequence_number); + // Inform the ack notifier of retransmissions so it can calculate the + // retransmit rate. + ack_notifier_manager_.OnPacketRetransmitted(original_sequence_number, + sequence_number, bytes); } if (pending_timer_transmission_count_ > 0) {
diff --git a/net/quic/quic_sent_packet_manager.h b/net/quic/quic_sent_packet_manager.h index 6bb2c778..c2a8ef6 100644 --- a/net/quic/quic_sent_packet_manager.h +++ b/net/quic/quic_sent_packet_manager.h
@@ -397,6 +397,9 @@ // Maximum number of tail loss probes to send before firing an RTO. size_t max_tail_loss_probes_; bool using_pacing_; + // If true, use the new RTO with loss based CWND reduction instead of the send + // algorithms's OnRetransmissionTimeout to reduce the congestion window. + bool use_new_rto_; // Vectors packets acked and lost as a result of the last congestion event. SendAlgorithmInterface::CongestionVector packets_acked_;
diff --git a/net/quic/quic_sent_packet_manager_test.cc b/net/quic/quic_sent_packet_manager_test.cc index 6275094..e9b169b 100644 --- a/net/quic/quic_sent_packet_manager_test.cc +++ b/net/quic/quic_sent_packet_manager_test.cc
@@ -16,6 +16,7 @@ using testing::AnyNumber; using testing::ElementsAre; using testing::IsEmpty; +using testing::Not; using testing::Pair; using testing::Pointwise; using testing::Return; @@ -1127,17 +1128,63 @@ } // Ack a retransmission. - if (FLAGS_quic_use_new_rto) { - EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout(true)); - } QuicAckFrame ack_frame; ack_frame.delta_time_largest_observed = QuicTime::Delta::Zero(); ack_frame.largest_observed = 102; for (int i = 0; i < 102; ++i) { ack_frame.missing_packets.insert(i); } + // Ensure no packets are lost. EXPECT_CALL(*send_algorithm_, - OnCongestionEvent(true, _, ElementsAre(Pair(102, _)), _)); + OnCongestionEvent(true, _, ElementsAre(Pair(102, _)), + /*lost_packets=*/IsEmpty())); + EXPECT_CALL(*network_change_visitor_, OnCongestionWindowChange()); + EXPECT_CALL(*network_change_visitor_, OnRttChange()); + if (FLAGS_quic_use_new_rto) { + EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout(true)); + } + manager_.OnIncomingAck(ack_frame, clock_.Now()); +} + +TEST_F(QuicSentPacketManagerTest, NewRetransmissionTimeout) { + ValueRestore<bool> old_flag(&FLAGS_quic_use_new_rto, true); + QuicConfig client_config; + QuicTagVector options; + options.push_back(kNRTO); + QuicSentPacketManagerPeer::SetIsServer(&manager_, false); + client_config.SetConnectionOptionsToSend(options); + EXPECT_CALL(*network_change_visitor_, OnCongestionWindowChange()); + EXPECT_CALL(*network_change_visitor_, OnRttChange()); + EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _, _)); + manager_.SetFromConfig(client_config); + EXPECT_TRUE(QuicSentPacketManagerPeer::GetUseNewRto(&manager_)); + + // Send 100 packets. + const size_t kNumSentPackets = 100; + for (size_t i = 1; i <= kNumSentPackets; ++i) { + SendDataPacket(i); + } + + EXPECT_FALSE(manager_.MaybeRetransmitTailLossProbe()); + manager_.OnRetransmissionTimeout(); + EXPECT_TRUE(manager_.HasPendingRetransmissions()); + EXPECT_EQ(100 * kDefaultLength, + QuicSentPacketManagerPeer::GetBytesInFlight(&manager_)); + RetransmitNextPacket(101); + RetransmitNextPacket(102); + EXPECT_FALSE(manager_.HasPendingRetransmissions()); + + // Ack a retransmission and expect no call to OnRetransmissionTimeout. + QuicAckFrame ack_frame; + ack_frame.delta_time_largest_observed = QuicTime::Delta::Zero(); + ack_frame.largest_observed = 102; + for (int i = 0; i < 102; ++i) { + ack_frame.missing_packets.insert(i); + } + // This will include packets in the lost packet map. + EXPECT_CALL(*send_algorithm_, + OnCongestionEvent(true, _, ElementsAre(Pair(102, _)), + /*lost_packets=*/Not(IsEmpty()))); EXPECT_CALL(*network_change_visitor_, OnCongestionWindowChange()); EXPECT_CALL(*network_change_visitor_, OnRttChange()); manager_.OnIncomingAck(ack_frame, clock_.Now()); @@ -1609,6 +1656,35 @@ EXPECT_EQ(0u, QuicSentPacketManagerPeer::GetMaxTailLossProbes(&manager_)); } +TEST_F(QuicSentPacketManagerTest, NegotiateNewRTOFromOptionsAtServer) { + EXPECT_FALSE(QuicSentPacketManagerPeer::GetUseNewRto(&manager_)); + QuicConfig config; + QuicTagVector options; + + options.push_back(kNRTO); + QuicConfigPeer::SetReceivedConnectionOptions(&config, options); + EXPECT_CALL(*network_change_visitor_, OnCongestionWindowChange()); + EXPECT_CALL(*network_change_visitor_, OnRttChange()); + EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _, _)); + manager_.SetFromConfig(config); + EXPECT_TRUE(QuicSentPacketManagerPeer::GetUseNewRto(&manager_)); +} + +TEST_F(QuicSentPacketManagerTest, NegotiateNewRTOFromOptionsAtClient) { + EXPECT_FALSE(QuicSentPacketManagerPeer::GetUseNewRto(&manager_)); + QuicConfig client_config; + QuicTagVector options; + + options.push_back(kNRTO); + QuicSentPacketManagerPeer::SetIsServer(&manager_, false); + client_config.SetConnectionOptionsToSend(options); + EXPECT_CALL(*network_change_visitor_, OnCongestionWindowChange()); + EXPECT_CALL(*network_change_visitor_, OnRttChange()); + EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _, _)); + manager_.SetFromConfig(client_config); + EXPECT_TRUE(QuicSentPacketManagerPeer::GetUseNewRto(&manager_)); +} + TEST_F(QuicSentPacketManagerTest, NegotiatePacingFromOptions) { EXPECT_FALSE(manager_.using_pacing());
diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc index c785ed6..da2f56c 100644 --- a/net/quic/quic_stream_factory.cc +++ b/net/quic/quic_stream_factory.cc
@@ -565,7 +565,6 @@ bool always_require_handshake_confirmation, bool disable_connection_pooling, int load_server_info_timeout, - bool disable_loading_server_info_for_new_servers, float load_server_info_timeout_srtt_multiplier, bool enable_truncated_connection_ids, const QuicTagVector& connection_options) @@ -586,8 +585,6 @@ always_require_handshake_confirmation), disable_connection_pooling_(disable_connection_pooling), load_server_info_timeout_ms_(load_server_info_timeout), - disable_loading_server_info_for_new_servers_( - disable_loading_server_info_for_new_servers), load_server_info_timeout_srtt_multiplier_( load_server_info_timeout_srtt_multiplier), enable_truncated_connection_ids_(enable_truncated_connection_ids), @@ -652,7 +649,7 @@ QuicServerInfo* quic_server_info = nullptr; if (quic_server_info_factory_) { bool load_from_disk_cache = true; - if (disable_loading_server_info_for_new_servers_) { + if (http_server_properties_) { const AlternateProtocolMap& alternate_protocol_map = http_server_properties_->alternate_protocol_map(); AlternateProtocolMap::const_iterator it = @@ -1108,6 +1105,11 @@ server_info->Start(); } + // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed. + tracked_objects::ScopedTracker tracking_profile6( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "422516 QuicStreamFactory::CreateSession61")); + *session = new QuicClientSession( connection, socket.Pass(), this, transport_security_state_, server_info.Pass(), config,
diff --git a/net/quic/quic_stream_factory.h b/net/quic/quic_stream_factory.h index ed5a930..f13156a 100644 --- a/net/quic/quic_stream_factory.h +++ b/net/quic/quic_stream_factory.h
@@ -105,7 +105,6 @@ bool always_require_handshake_confirmation, bool disable_connection_pooling, int load_server_info_timeout, - bool disable_loading_server_info_for_new_servers, float load_server_info_timeout_srtt_multiplier, bool enable_truncated_connection_ids, const QuicTagVector& connection_options); @@ -297,11 +296,6 @@ // |load_server_info_timeout_ms_| to 0. int load_server_info_timeout_ms_; - // Set to disable loading of QUIC server information from disk cache for new - // servers. New servers are those servers for which there is no QUIC protocol - // entry in AlternateProtocolMap. - bool disable_loading_server_info_for_new_servers_; - // 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
diff --git a/net/quic/quic_stream_factory_test.cc b/net/quic/quic_stream_factory_test.cc index 345b818d..2ce6ef4 100644 --- a/net/quic/quic_stream_factory_test.cc +++ b/net/quic/quic_stream_factory_test.cc
@@ -163,7 +163,6 @@ /*always_require_handshake_confirmation=*/false, /*disable_connection_pooling=*/false, /*load_server_info_timeout=*/0u, - /*disable_loading_server_info_for_new_servers=*/false, /*load_server_info_timeout_srtt_multiplier=*/0.0f, /*enable_truncated_connection_ids=*/true, QuicTagVector()),
diff --git a/net/quic/quic_stream_sequencer.h b/net/quic/quic_stream_sequencer.h index 025dca4..f34d735 100644 --- a/net/quic/quic_stream_sequencer.h +++ b/net/quic/quic_stream_sequencer.h
@@ -23,7 +23,6 @@ // Buffers frames until we have something which can be passed // up to the next layer. -// TOOD(alyssar) add some checks for overflow attempts [1, 256,] [2, 256] class NET_EXPORT_PRIVATE QuicStreamSequencer { public: explicit QuicStreamSequencer(ReliableQuicStream* quic_stream);
diff --git a/net/quic/test_tools/quic_sent_packet_manager_peer.cc b/net/quic/test_tools/quic_sent_packet_manager_peer.cc index 311b688..4e182ab 100644 --- a/net/quic/test_tools/quic_sent_packet_manager_peer.cc +++ b/net/quic/test_tools/quic_sent_packet_manager_peer.cc
@@ -26,6 +26,12 @@ } // static +bool QuicSentPacketManagerPeer::GetUseNewRto( + QuicSentPacketManager* sent_packet_manager) { + return sent_packet_manager->use_new_rto_; +} + +// static QuicByteCount QuicSentPacketManagerPeer::GetReceiveWindow( QuicSentPacketManager* sent_packet_manager) { return sent_packet_manager->receive_buffer_bytes_;
diff --git a/net/quic/test_tools/quic_sent_packet_manager_peer.h b/net/quic/test_tools/quic_sent_packet_manager_peer.h index 2d850d3..6ac34ffc 100644 --- a/net/quic/test_tools/quic_sent_packet_manager_peer.h +++ b/net/quic/test_tools/quic_sent_packet_manager_peer.h
@@ -22,6 +22,8 @@ static void SetMaxTailLossProbes( QuicSentPacketManager* sent_packet_manager, size_t max_tail_loss_probes); + static bool GetUseNewRto(QuicSentPacketManager* sent_packet_manager); + static QuicByteCount GetReceiveWindow( QuicSentPacketManager* sent_packet_manager);
diff --git a/net/server/http_server_unittest.cc b/net/server/http_server_unittest.cc index c25c03e..aaad7b8 100644 --- a/net/server/http_server_unittest.cc +++ b/net/server/http_server_unittest.cc
@@ -278,7 +278,7 @@ TEST_F(HttpServerTest, RequestWithHeaders) { TestHttpClient client; ASSERT_EQ(OK, client.ConnectAndWait(server_address_)); - const char* kHeaders[][3] = { + const char* const kHeaders[][3] = { {"Header", ": ", "1"}, {"HeaderWithNoWhitespace", ":", "1"}, {"HeaderWithWhitespace", " : \t ", "1 1 1 \t "}, @@ -308,7 +308,7 @@ TEST_F(HttpServerTest, RequestWithDuplicateHeaders) { TestHttpClient client; ASSERT_EQ(OK, client.ConnectAndWait(server_address_)); - const char* kHeaders[][3] = { + const char* const kHeaders[][3] = { {"FirstHeader", ": ", "1"}, {"DuplicateHeader", ": ", "2"}, {"MiddleHeader", ": ", "3"}, @@ -336,7 +336,7 @@ TEST_F(HttpServerTest, HasHeaderValueTest) { TestHttpClient client; ASSERT_EQ(OK, client.ConnectAndWait(server_address_)); - const char* kHeaders[] = { + const char* const kHeaders[] = { "Header: Abcd", "HeaderWithNoWhitespace:E", "HeaderWithWhitespace : \t f \t ",
diff --git a/net/socket/socket_test_util.cc b/net/socket/socket_test_util.cc index 658182b..791c9f6 100644 --- a/net/socket/socket_test_util.cc +++ b/net/socket/socket_test_util.cc
@@ -24,6 +24,7 @@ #include "net/http/http_response_headers.h" #include "net/socket/client_socket_pool_histograms.h" #include "net/socket/socket.h" +#include "net/socket/websocket_endpoint_lock_manager.h" #include "net/ssl/ssl_cert_request_info.h" #include "net/ssl/ssl_connection_status_flags.h" #include "net/ssl/ssl_info.h" @@ -1989,6 +1990,21 @@ return transport_pool_->ReleaseSocket(group_name, socket.Pass(), id); } +ScopedWebSocketEndpointZeroUnlockDelay:: + ScopedWebSocketEndpointZeroUnlockDelay() { + old_delay_ = + WebSocketEndpointLockManager::GetInstance()->SetUnlockDelayForTesting( + base::TimeDelta()); +} + +ScopedWebSocketEndpointZeroUnlockDelay:: + ~ScopedWebSocketEndpointZeroUnlockDelay() { + base::TimeDelta active_delay = + WebSocketEndpointLockManager::GetInstance()->SetUnlockDelayForTesting( + old_delay_); + EXPECT_EQ(active_delay, base::TimeDelta()); +} + const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 }; const int kSOCKS5GreetRequestLength = arraysize(kSOCKS5GreetRequest);
diff --git a/net/socket/socket_test_util.h b/net/socket/socket_test_util.h index 6d3162b..d6c7aba 100644 --- a/net/socket/socket_test_util.h +++ b/net/socket/socket_test_util.h
@@ -18,6 +18,7 @@ #include "base/memory/scoped_vector.h" #include "base/memory/weak_ptr.h" #include "base/strings/string16.h" +#include "base/time/time.h" #include "net/base/address_list.h" #include "net/base/io_buffer.h" #include "net/base/net_errors.h" @@ -1319,6 +1320,18 @@ DISALLOW_COPY_AND_ASSIGN(MockSOCKSClientSocketPool); }; +// Convenience class to temporarily set the WebSocketEndpointLockManager unlock +// delay to zero for testing purposes. Automatically restores the original value +// when destroyed. +class ScopedWebSocketEndpointZeroUnlockDelay { + public: + ScopedWebSocketEndpointZeroUnlockDelay(); + ~ScopedWebSocketEndpointZeroUnlockDelay(); + + private: + base::TimeDelta old_delay_; +}; + // Constants for a successful SOCKS v5 handshake. extern const char kSOCKS5GreetRequest[]; extern const int kSOCKS5GreetRequestLength;
diff --git a/net/socket/ssl_client_socket_unittest.cc b/net/socket/ssl_client_socket_unittest.cc index 2fc6523..287dbb8 100644 --- a/net/socket/ssl_client_socket_unittest.cc +++ b/net/socket/ssl_client_socket_unittest.cc
@@ -2322,15 +2322,15 @@ EXPECT_TRUE(sock->IsConnected()); const int kKeyingMaterialSize = 32; - const char* kKeyingLabel1 = "client-socket-test-1"; - const char* kKeyingContext = ""; + const char kKeyingLabel1[] = "client-socket-test-1"; + const char kKeyingContext[] = ""; unsigned char client_out1[kKeyingMaterialSize]; memset(client_out1, 0, sizeof(client_out1)); rv = sock->ExportKeyingMaterial( kKeyingLabel1, false, kKeyingContext, client_out1, sizeof(client_out1)); EXPECT_EQ(rv, OK); - const char* kKeyingLabel2 = "client-socket-test-2"; + const char kKeyingLabel2[] = "client-socket-test-2"; unsigned char client_out2[kKeyingMaterialSize]; memset(client_out2, 0, sizeof(client_out2)); rv = sock->ExportKeyingMaterial(
diff --git a/net/socket/ssl_server_socket_unittest.cc b/net/socket/ssl_server_socket_unittest.cc index 5fabdd2e..d13dba8 100644 --- a/net/socket/ssl_server_socket_unittest.cc +++ b/net/socket/ssl_server_socket_unittest.cc
@@ -535,8 +535,8 @@ } const int kKeyingMaterialSize = 32; - const char* kKeyingLabel = "EXPERIMENTAL-server-socket-test"; - const char* kKeyingContext = ""; + const char kKeyingLabel[] = "EXPERIMENTAL-server-socket-test"; + const char kKeyingContext[] = ""; unsigned char server_out[kKeyingMaterialSize]; int rv = server_socket_->ExportKeyingMaterial(kKeyingLabel, false, kKeyingContext, @@ -550,7 +550,7 @@ ASSERT_EQ(OK, rv); EXPECT_EQ(0, memcmp(server_out, client_out, sizeof(server_out))); - const char* kKeyingLabelBad = "EXPERIMENTAL-server-socket-test-bad"; + const char kKeyingLabelBad[] = "EXPERIMENTAL-server-socket-test-bad"; unsigned char client_bad[kKeyingMaterialSize]; rv = client_socket_->ExportKeyingMaterial(kKeyingLabelBad, false, kKeyingContext,
diff --git a/net/socket/websocket_endpoint_lock_manager.cc b/net/socket/websocket_endpoint_lock_manager.cc index e578bb2..1bccb1d 100644 --- a/net/socket/websocket_endpoint_lock_manager.cc +++ b/net/socket/websocket_endpoint_lock_manager.cc
@@ -6,12 +6,23 @@ #include <utility> +#include "base/bind.h" #include "base/logging.h" +#include "base/message_loop/message_loop.h" #include "net/base/net_errors.h" #include "net/base/net_log.h" namespace net { +namespace { + +// This delay prevents DoS attacks. +// TODO(ricea): Replace this with randomised truncated exponential backoff. +// See crbug.com/377613. +const int kUnlockDelayInMs = 10; + +} // namespace + WebSocketEndpointLockManager::Waiter::~Waiter() { if (next()) { DCHECK(previous()); @@ -65,23 +76,31 @@ << lock_info_it->first.ToString() << " (" << socket_lock_info_map_.size() << " socket(s) left)"; socket_lock_info_map_.erase(socket_it); - DCHECK(socket == lock_info_it->second.socket); + DCHECK_EQ(socket, lock_info_it->second.socket); lock_info_it->second.socket = NULL; - UnlockEndpointByIterator(lock_info_it); + UnlockEndpointAfterDelay(lock_info_it->first); } void WebSocketEndpointLockManager::UnlockEndpoint(const IPEndPoint& endpoint) { LockInfoMap::iterator lock_info_it = lock_info_map_.find(endpoint); if (lock_info_it == lock_info_map_.end()) return; - - UnlockEndpointByIterator(lock_info_it); + if (lock_info_it->second.socket) + EraseSocket(lock_info_it); + UnlockEndpointAfterDelay(endpoint); } bool WebSocketEndpointLockManager::IsEmpty() const { return lock_info_map_.empty() && socket_lock_info_map_.empty(); } +base::TimeDelta WebSocketEndpointLockManager::SetUnlockDelayForTesting( + base::TimeDelta new_delay) { + base::TimeDelta old_delay = unlock_delay_; + unlock_delay_ = new_delay; + return old_delay; +} + WebSocketEndpointLockManager::LockInfo::LockInfo() : socket(NULL) {} WebSocketEndpointLockManager::LockInfo::~LockInfo() { DCHECK(!socket); @@ -92,17 +111,37 @@ DCHECK(!rhs.queue); } -WebSocketEndpointLockManager::WebSocketEndpointLockManager() {} +WebSocketEndpointLockManager::WebSocketEndpointLockManager() + : unlock_delay_(base::TimeDelta::FromMilliseconds(kUnlockDelayInMs)), + pending_unlock_count_(0), + weak_factory_(this) { +} WebSocketEndpointLockManager::~WebSocketEndpointLockManager() { - DCHECK(lock_info_map_.empty()); + DCHECK_EQ(lock_info_map_.size(), pending_unlock_count_); DCHECK(socket_lock_info_map_.empty()); } -void WebSocketEndpointLockManager::UnlockEndpointByIterator( - LockInfoMap::iterator lock_info_it) { - if (lock_info_it->second.socket) - EraseSocket(lock_info_it); +void WebSocketEndpointLockManager::UnlockEndpointAfterDelay( + const IPEndPoint& endpoint) { + DVLOG(3) << "Delaying " << unlock_delay_.InMilliseconds() + << "ms before unlocking endpoint " << endpoint.ToString(); + ++pending_unlock_count_; + base::MessageLoop::current()->PostDelayedTask( + FROM_HERE, + base::Bind(&WebSocketEndpointLockManager::DelayedUnlockEndpoint, + weak_factory_.GetWeakPtr(), endpoint), + unlock_delay_); +} + +void WebSocketEndpointLockManager::DelayedUnlockEndpoint( + const IPEndPoint& endpoint) { + LockInfoMap::iterator lock_info_it = lock_info_map_.find(endpoint); + DCHECK_GT(pending_unlock_count_, 0U); + --pending_unlock_count_; + if (lock_info_it == lock_info_map_.end()) + return; + DCHECK(!lock_info_it->second.socket); LockInfo::WaiterQueue* queue = lock_info_it->second.queue.get(); DCHECK(queue); if (queue->empty()) { @@ -115,7 +154,6 @@ << " and activating next waiter"; Waiter* next_job = queue->head()->value(); next_job->RemoveFromList(); - // This must be last to minimise the excitement caused by re-entrancy. next_job->GotEndpointLock(); }
diff --git a/net/socket/websocket_endpoint_lock_manager.h b/net/socket/websocket_endpoint_lock_manager.h index d5cad50..bddd5455 100644 --- a/net/socket/websocket_endpoint_lock_manager.h +++ b/net/socket/websocket_endpoint_lock_manager.h
@@ -11,6 +11,7 @@ #include "base/logging.h" #include "base/macros.h" #include "base/memory/singleton.h" +#include "base/time/time.h" #include "net/base/ip_endpoint.h" #include "net/base/net_export.h" #include "net/socket/websocket_transport_client_socket_pool.h" @@ -19,8 +20,25 @@ class StreamSocket; +// Keep track of ongoing WebSocket connections in order to satisfy the WebSocket +// connection throttling requirements described in RFC6455 4.1.2: +// +// 2. If the client already has a WebSocket connection to the remote +// host (IP address) identified by /host/ and port /port/ pair, even +// if the remote host is known by another name, the client MUST wait +// until that connection has been established or for that connection +// to have failed. There MUST be no more than one connection in a +// CONNECTING state. If multiple connections to the same IP address +// are attempted simultaneously, the client MUST serialize them so +// that there is no more than one connection at a time running +// through the following steps. +// +// This class is neither thread-safe nor thread-compatible. +// TODO(ricea): Make this class thread-compatible by making it not be a +// singleton. class NET_EXPORT_PRIVATE WebSocketEndpointLockManager { public: + // Implement this interface to wait for an endpoint to be available. class NET_EXPORT_PRIVATE Waiter : public base::LinkNode<Waiter> { public: // If the node is in a list, removes it. @@ -45,22 +63,28 @@ // UnlockSocket(). void RememberSocket(StreamSocket* socket, const IPEndPoint& endpoint); - // Releases the lock on the endpoint that was associated with |socket| by - // RememberSocket(). If appropriate, triggers the next socket connection. - // Should be called exactly once for each |socket| that was passed to - // RememberSocket(). Does nothing if UnlockEndpoint() has been called since + // Removes the socket association that was recorded by RememberSocket(), then + // asynchronously releases the lock on the endpoint after a delay. If + // appropriate, calls |waiter->GetEndpointLock()| when the lock is + // released. Should be called exactly once for each |socket| that was passed + // to RememberSocket(). Does nothing if UnlockEndpoint() has been called since // the call to RememberSocket(). void UnlockSocket(StreamSocket* socket); - // Releases the lock on |endpoint|. Does nothing if |endpoint| is not locked. - // Removes any socket association that was recorded with RememberSocket(). If - // appropriate, calls |waiter->GotEndpointLock()|. + // Asynchronously releases the lock on |endpoint| after a delay. Does nothing + // if |endpoint| is not locked. Removes any socket association that was + // recorded with RememberSocket(). If appropriate, calls + // |waiter->GotEndpointLock()| when the lock is released. void UnlockEndpoint(const IPEndPoint& endpoint); // Checks that |lock_info_map_| and |socket_lock_info_map_| are empty. For // tests. bool IsEmpty() const; + // Changes the value of the unlock delay. Returns the previous value of the + // delay. + base::TimeDelta SetUnlockDelayForTesting(base::TimeDelta new_delay); + private: struct LockInfo { typedef base::LinkedList<Waiter> WaiterQueue; @@ -97,7 +121,8 @@ WebSocketEndpointLockManager(); ~WebSocketEndpointLockManager(); - void UnlockEndpointByIterator(LockInfoMap::iterator lock_info_it); + void UnlockEndpointAfterDelay(const IPEndPoint& endpoint); + void DelayedUnlockEndpoint(const IPEndPoint& endpoint); void EraseSocket(LockInfoMap::iterator lock_info_it); // If an entry is present in the map for a particular endpoint, then that @@ -111,6 +136,16 @@ // is non-NULL if and only if there is an entry in this map for the socket. SocketLockInfoMap socket_lock_info_map_; + // Time to wait between a call to Unlock* and actually unlocking the socket. + base::TimeDelta unlock_delay_; + + // Number of sockets currently pending unlock. + size_t pending_unlock_count_; + + // The messsage loop holding the unlock delay callback may outlive this + // object. + base::WeakPtrFactory<WebSocketEndpointLockManager> weak_factory_; + friend struct DefaultSingletonTraits<WebSocketEndpointLockManager>; DISALLOW_COPY_AND_ASSIGN(WebSocketEndpointLockManager);
diff --git a/net/socket/websocket_endpoint_lock_manager_unittest.cc b/net/socket/websocket_endpoint_lock_manager_unittest.cc index 1626aa90..2974b5a3 100644 --- a/net/socket/websocket_endpoint_lock_manager_unittest.cc +++ b/net/socket/websocket_endpoint_lock_manager_unittest.cc
@@ -4,6 +4,9 @@ #include "net/socket/websocket_endpoint_lock_manager.h" +#include "base/message_loop/message_loop.h" +#include "base/run_loop.h" +#include "base/time/time.h" #include "net/base/net_errors.h" #include "net/socket/next_proto.h" #include "net/socket/socket_test_util.h" @@ -94,6 +97,8 @@ WebSocketEndpointLockManagerTest() : instance_(WebSocketEndpointLockManager::GetInstance()) {} ~WebSocketEndpointLockManagerTest() override { + // Permit any pending asynchronous unlock operations to complete. + RunUntilIdle(); // If this check fails then subsequent tests may fail. CHECK(instance_->IsEmpty()); } @@ -109,10 +114,14 @@ void UnlockDummyEndpoint(int times) { for (int i = 0; i < times; ++i) { instance()->UnlockEndpoint(DummyEndpoint()); + RunUntilIdle(); } } + static void RunUntilIdle() { base::RunLoop().RunUntilIdle(); } + WebSocketEndpointLockManager* const instance_; + ScopedWebSocketEndpointZeroUnlockDelay zero_unlock_delay_; }; TEST_F(WebSocketEndpointLockManagerTest, GetInstanceWorks) { @@ -131,6 +140,7 @@ TEST_F(WebSocketEndpointLockManagerTest, GotEndpointLockNotCalledOnOk) { FakeWaiter waiter; EXPECT_EQ(OK, instance()->LockEndpoint(DummyEndpoint(), &waiter)); + RunUntilIdle(); EXPECT_FALSE(waiter.called()); UnlockDummyEndpoint(1); @@ -141,6 +151,7 @@ EXPECT_EQ(OK, instance()->LockEndpoint(DummyEndpoint(), &waiters[0])); EXPECT_EQ(ERR_IO_PENDING, instance()->LockEndpoint(DummyEndpoint(), &waiters[1])); + RunUntilIdle(); EXPECT_FALSE(waiters[1].called()); UnlockDummyEndpoint(2); @@ -152,6 +163,7 @@ EXPECT_EQ(ERR_IO_PENDING, instance()->LockEndpoint(DummyEndpoint(), &waiters[1])); instance()->UnlockEndpoint(DummyEndpoint()); + RunUntilIdle(); EXPECT_TRUE(waiters[1].called()); UnlockDummyEndpoint(1); @@ -169,6 +181,7 @@ } instance()->UnlockEndpoint(DummyEndpoint()); + RunUntilIdle(); FakeWaiter second_lock_holder; EXPECT_EQ(OK, instance()->LockEndpoint(DummyEndpoint(), &second_lock_holder)); @@ -185,6 +198,7 @@ instance()->RememberSocket(&dummy_socket, DummyEndpoint()); instance()->UnlockSocket(&dummy_socket); + RunUntilIdle(); EXPECT_TRUE(waiters[1].called()); UnlockDummyEndpoint(1); @@ -199,6 +213,7 @@ EXPECT_EQ(OK, instance()->LockEndpoint(DummyEndpoint(), &waiter)); instance()->RememberSocket(&dummy_socket, DummyEndpoint()); instance()->UnlockEndpoint(DummyEndpoint()); + RunUntilIdle(); EXPECT_TRUE(instance()->IsEmpty()); } @@ -213,12 +228,70 @@ instance()->RememberSocket(&dummy_sockets[0], DummyEndpoint()); instance()->UnlockEndpoint(DummyEndpoint()); + RunUntilIdle(); EXPECT_TRUE(waiters[1].called()); instance()->RememberSocket(&dummy_sockets[1], DummyEndpoint()); UnlockDummyEndpoint(1); } +// Calling UnlockSocket() after UnlockEndpoint() does nothing. +TEST_F(WebSocketEndpointLockManagerTest, + UnlockSocketAfterUnlockEndpointDoesNothing) { + FakeWaiter waiters[3]; + FakeStreamSocket dummy_socket; + + EXPECT_EQ(OK, instance()->LockEndpoint(DummyEndpoint(), &waiters[0])); + EXPECT_EQ(ERR_IO_PENDING, + instance()->LockEndpoint(DummyEndpoint(), &waiters[1])); + EXPECT_EQ(ERR_IO_PENDING, + instance()->LockEndpoint(DummyEndpoint(), &waiters[2])); + instance()->RememberSocket(&dummy_socket, DummyEndpoint()); + instance()->UnlockEndpoint(DummyEndpoint()); + instance()->UnlockSocket(&dummy_socket); + RunUntilIdle(); + EXPECT_TRUE(waiters[1].called()); + EXPECT_FALSE(waiters[2].called()); + + UnlockDummyEndpoint(2); +} + +// UnlockEndpoint() should always be asynchronous. +TEST_F(WebSocketEndpointLockManagerTest, UnlockEndpointIsAsynchronous) { + FakeWaiter waiters[2]; + EXPECT_EQ(OK, instance()->LockEndpoint(DummyEndpoint(), &waiters[0])); + EXPECT_EQ(ERR_IO_PENDING, + instance()->LockEndpoint(DummyEndpoint(), &waiters[1])); + + instance()->UnlockEndpoint(DummyEndpoint()); + EXPECT_FALSE(waiters[1].called()); + RunUntilIdle(); + EXPECT_TRUE(waiters[1].called()); + + UnlockDummyEndpoint(1); +} + +// UnlockEndpoint() should normally have a delay. +TEST_F(WebSocketEndpointLockManagerTest, UnlockEndpointIsDelayed) { + const base::TimeDelta one_millisecond = base::TimeDelta::FromMilliseconds(1); + instance()->SetUnlockDelayForTesting(one_millisecond); + FakeWaiter waiters[2]; + EXPECT_EQ(OK, instance()->LockEndpoint(DummyEndpoint(), &waiters[0])); + EXPECT_EQ(ERR_IO_PENDING, + instance()->LockEndpoint(DummyEndpoint(), &waiters[1])); + + instance()->UnlockEndpoint(DummyEndpoint()); + RunUntilIdle(); + EXPECT_FALSE(waiters[1].called()); + base::RunLoop run_loop; + base::MessageLoop::current()->PostDelayedTask( + FROM_HERE, run_loop.QuitClosure(), one_millisecond); + run_loop.Run(); + EXPECT_TRUE(waiters[1].called()); + instance()->SetUnlockDelayForTesting(base::TimeDelta()); + UnlockDummyEndpoint(1); +} + } // namespace } // namespace net
diff --git a/net/socket/websocket_transport_client_socket_pool_unittest.cc b/net/socket/websocket_transport_client_socket_pool_unittest.cc index 2189181..03bdf43 100644 --- a/net/socket/websocket_transport_client_socket_pool_unittest.cc +++ b/net/socket/websocket_transport_client_socket_pool_unittest.cc
@@ -48,7 +48,7 @@ run_loop.Run(); } -class WebSocketTransportClientSocketPoolTest : public testing::Test { +class WebSocketTransportClientSocketPoolTest : public ::testing::Test { protected: WebSocketTransportClientSocketPoolTest() : params_(new TransportSocketParams( @@ -68,10 +68,15 @@ NULL) {} ~WebSocketTransportClientSocketPoolTest() override { + RunUntilIdle(); + // ReleaseAllConnections() calls RunUntilIdle() after releasing each + // connection. ReleaseAllConnections(ClientSocketPoolTest::NO_KEEP_ALIVE); EXPECT_TRUE(WebSocketEndpointLockManager::GetInstance()->IsEmpty()); } + static void RunUntilIdle() { base::RunLoop().RunUntilIdle(); } + int StartRequest(const std::string& group_name, RequestPriority priority) { scoped_refptr<TransportSocketParams> params( new TransportSocketParams( @@ -108,6 +113,7 @@ MockTransportClientSocketFactory client_socket_factory_; WebSocketTransportClientSocketPool pool_; ClientSocketPoolTest test_base_; + ScopedWebSocketEndpointZeroUnlockDelay zero_unlock_delay_; private: DISALLOW_COPY_AND_ASSIGN(WebSocketTransportClientSocketPoolTest); @@ -502,7 +508,7 @@ EXPECT_EQ(OK, request(0)->WaitForResult()); EXPECT_FALSE(request(1)->handle()->is_initialized()); request(0)->handle()->Reset(); - base::RunLoop().RunUntilIdle(); + RunUntilIdle(); EXPECT_TRUE(request(1)->handle()->is_initialized()); } @@ -518,7 +524,7 @@ EXPECT_EQ(OK, callback.WaitForResult()); EXPECT_FALSE(request(0)->handle()->is_initialized()); handle.reset(); - base::RunLoop().RunUntilIdle(); + RunUntilIdle(); EXPECT_TRUE(request(0)->handle()->is_initialized()); } @@ -531,7 +537,7 @@ EXPECT_EQ(OK, request(0)->WaitForResult()); EXPECT_FALSE(request(1)->handle()->is_initialized()); WebSocketTransportClientSocketPool::UnlockEndpoint(request(0)->handle()); - base::RunLoop().RunUntilIdle(); + RunUntilIdle(); EXPECT_TRUE(request(1)->handle()->is_initialized()); } @@ -548,7 +554,7 @@ EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); - base::RunLoop().RunUntilIdle(); + RunUntilIdle(); pool_.CancelRequest("a", request(0)->handle()); EXPECT_EQ(OK, request(1)->WaitForResult()); } @@ -902,8 +908,9 @@ TEST_F(WebSocketTransportClientSocketPoolTest, MaxSocketsEnforced) { host_resolver_->set_synchronous_mode(true); for (int i = 0; i < kMaxSockets; ++i) { - EXPECT_EQ(OK, StartRequest("a", kDefaultPriority)); + ASSERT_EQ(OK, StartRequest("a", kDefaultPriority)); WebSocketTransportClientSocketPool::UnlockEndpoint(request(i)->handle()); + RunUntilIdle(); } EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); } @@ -914,13 +921,13 @@ } // Now there are 32 sockets waiting to connect, and one stalled. for (int i = 0; i < kMaxSockets; ++i) { - base::RunLoop().RunUntilIdle(); + RunUntilIdle(); EXPECT_TRUE(request(i)->handle()->is_initialized()); EXPECT_TRUE(request(i)->handle()->socket()); WebSocketTransportClientSocketPool::UnlockEndpoint(request(i)->handle()); } // Now there are 32 sockets connected, and one stalled. - base::RunLoop().RunUntilIdle(); + RunUntilIdle(); EXPECT_FALSE(request(kMaxSockets)->handle()->is_initialized()); EXPECT_FALSE(request(kMaxSockets)->handle()->socket()); } @@ -928,8 +935,9 @@ TEST_F(WebSocketTransportClientSocketPoolTest, StalledSocketReleased) { host_resolver_->set_synchronous_mode(true); for (int i = 0; i < kMaxSockets; ++i) { - EXPECT_EQ(OK, StartRequest("a", kDefaultPriority)); + ASSERT_EQ(OK, StartRequest("a", kDefaultPriority)); WebSocketTransportClientSocketPool::UnlockEndpoint(request(i)->handle()); + RunUntilIdle(); } EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); @@ -953,7 +961,7 @@ } EXPECT_EQ(OK, request(0)->WaitForResult()); request(1)->handle()->Reset(); - base::RunLoop().RunUntilIdle(); + RunUntilIdle(); EXPECT_FALSE(pool_.IsStalled()); } @@ -972,6 +980,7 @@ EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); } request(kMaxSockets)->handle()->Reset(); + RunUntilIdle(); EXPECT_FALSE(pool_.IsStalled()); } @@ -1114,6 +1123,7 @@ request(0)->handle()->Reset(); // calls CancelRequest() + RunUntilIdle(); // We should now be able to create a new connection without blocking on the // endpoint lock. EXPECT_EQ(OK, StartRequest("a", kDefaultPriority)); @@ -1123,11 +1133,12 @@ // Endpoint, not two. TEST_F(WebSocketTransportClientSocketPoolTest, EndpointLockIsOnlyReleasedOnce) { host_resolver_->set_synchronous_mode(true); - EXPECT_EQ(OK, StartRequest("a", kDefaultPriority)); + ASSERT_EQ(OK, StartRequest("a", kDefaultPriority)); EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority)); // First socket completes handshake. WebSocketTransportClientSocketPool::UnlockEndpoint(request(0)->handle()); + RunUntilIdle(); // First socket is closed. request(0)->handle()->Reset(); // Second socket should have been released.
diff --git a/net/spdy/spdy_headers_block_parser.cc b/net/spdy/spdy_headers_block_parser.cc index 1ec0d0da..154f647 100644 --- a/net/spdy/spdy_headers_block_parser.cc +++ b/net/spdy/spdy_headers_block_parser.cc
@@ -26,7 +26,7 @@ remaining_key_value_pairs_for_frame_(0), handler_(handler), stream_id_(kInvalidStreamId), - error_(OK), + error_(NO_PARSER_ERROR), spdy_version_(spdy_version) { // The handler that we set must not be NULL. DCHECK(handler_ != NULL); @@ -39,9 +39,9 @@ const char* headers_data, size_t headers_data_length) { if (error_ == NEED_MORE_DATA) { - error_ = OK; + error_ = NO_PARSER_ERROR; } - if (error_ != OK) { + if (error_ != NO_PARSER_ERROR) { LOG(DFATAL) << "Unexpected error: " << error_; return false; } @@ -73,7 +73,7 @@ // from last invocation, plus newly-available headers data. Reader reader(prefix.buffer(), prefix.length(), headers_data, headers_data_length); - while (error_ == OK) { + while (error_ == NO_PARSER_ERROR) { ParserState next_state(FINISHED_HEADER); switch (state_) { @@ -119,7 +119,7 @@ break; } - if (error_ == OK) { + if (error_ == NO_PARSER_ERROR) { state_ = next_state; if (next_state == READING_HEADER_BLOCK_LEN) { @@ -138,24 +138,23 @@ headers_block_prefix_.Pin(); } } - return error_ == OK; + return error_ == NO_PARSER_ERROR; } void SpdyHeadersBlockParser::ParseBlockLength(Reader* reader) { ParseLength(reader, &remaining_key_value_pairs_for_frame_); - if (error_ == OK && - remaining_key_value_pairs_for_frame_ > max_headers_in_block_) { + if (error_ == NO_PARSER_ERROR && + remaining_key_value_pairs_for_frame_ > max_headers_in_block_) { error_ = HEADER_BLOCK_TOO_LARGE; } - if (error_ == OK) { + if (error_ == NO_PARSER_ERROR) { handler_->OnHeaderBlock(remaining_key_value_pairs_for_frame_); } } void SpdyHeadersBlockParser::ParseFieldLength(Reader* reader) { ParseLength(reader, &next_field_length_); - if (error_ == OK && - next_field_length_ > kMaximumFieldLength) { + if (error_ == NO_PARSER_ERROR && next_field_length_ > kMaximumFieldLength) { error_ = HEADER_FIELD_TOO_LARGE; } }
diff --git a/net/spdy/spdy_headers_block_parser.h b/net/spdy/spdy_headers_block_parser.h index a9dfaa64..54334b2 100644 --- a/net/spdy/spdy_headers_block_parser.h +++ b/net/spdy/spdy_headers_block_parser.h
@@ -61,7 +61,7 @@ const char* headers_data, size_t len); enum ParserError { - OK, + NO_PARSER_ERROR, // Set when parsing failed due to insufficient data. // This error is recoverable, by passing in new data. NEED_MORE_DATA,
diff --git a/net/spdy/spdy_headers_block_parser_test.cc b/net/spdy/spdy_headers_block_parser_test.cc index 81338883..2bb888d 100644 --- a/net/spdy/spdy_headers_block_parser_test.cc +++ b/net/spdy/spdy_headers_block_parser_test.cc
@@ -129,7 +129,7 @@ EXPECT_TRUE(parser_-> HandleControlFrameHeadersData(1, headers.c_str(), headers.length())); - EXPECT_EQ(SpdyHeadersBlockParser::OK, parser_->get_error()); + EXPECT_EQ(SpdyHeadersBlockParser::NO_PARSER_ERROR, parser_->get_error()); } TEST_P(SpdyHeadersBlockParserTest, NullsSupportedTest) { @@ -147,7 +147,7 @@ EXPECT_TRUE(parser_-> HandleControlFrameHeadersData(1, headers.c_str(), headers.length())); - EXPECT_EQ(SpdyHeadersBlockParser::OK, parser_->get_error()); + EXPECT_EQ(SpdyHeadersBlockParser::NO_PARSER_ERROR, parser_->get_error()); } TEST_P(SpdyHeadersBlockParserTest, MultipleBlocksAndHeadersWithPartialData) { @@ -178,7 +178,8 @@ if ((it + 1) == headers.end()) { // Last byte completes the block. EXPECT_TRUE(parser_->HandleControlFrameHeadersData(i, &(*it), 1)); - EXPECT_EQ(SpdyHeadersBlockParser::OK, parser_->get_error()); + EXPECT_EQ(SpdyHeadersBlockParser::NO_PARSER_ERROR, + parser_->get_error()); } else { EXPECT_FALSE(parser_->HandleControlFrameHeadersData(i, &(*it), 1)); EXPECT_EQ(SpdyHeadersBlockParser::NEED_MORE_DATA, parser_->get_error()); @@ -203,7 +204,7 @@ if ((it + 1) == headers.end()) { // Last byte completes the block. EXPECT_TRUE(parser_->HandleControlFrameHeadersData(1, &(*it), 1)); - EXPECT_EQ(SpdyHeadersBlockParser::OK, parser_->get_error()); + EXPECT_EQ(SpdyHeadersBlockParser::NO_PARSER_ERROR, parser_->get_error()); } else { EXPECT_FALSE(parser_->HandleControlFrameHeadersData(1, &(*it), 1)); EXPECT_EQ(SpdyHeadersBlockParser::NEED_MORE_DATA, parser_->get_error());
diff --git a/net/spdy/spdy_session.cc b/net/spdy/spdy_session.cc index 575cee2..a6478df 100644 --- a/net/spdy/spdy_session.cc +++ b/net/spdy/spdy_session.cc
@@ -450,8 +450,8 @@ to_insert = request_headers; } else { const char* host = protocol_version >= SPDY4 ? ":authority" : ":host"; - static const char* scheme = ":scheme"; - static const char* path = ":path"; + static const char scheme[] = ":scheme"; + static const char path[] = ":path"; if (it->first == host || it->first == scheme || it->first == path) to_insert = request_headers; }
diff --git a/net/ssl/client_cert_store_chromeos.h b/net/ssl/client_cert_store_chromeos.h index 5e9922d..2bc359c 100644 --- a/net/ssl/client_cert_store_chromeos.h +++ b/net/ssl/client_cert_store_chromeos.h
@@ -38,19 +38,19 @@ ClientCertStoreChromeOS( scoped_ptr<CertFilter> cert_filter, const PasswordDelegateFactory& password_delegate_factory); - virtual ~ClientCertStoreChromeOS(); + ~ClientCertStoreChromeOS() override; // ClientCertStoreNSS: - virtual void GetClientCerts(const SSLCertRequestInfo& cert_request_info, - CertificateList* selected_certs, - const base::Closure& callback) override; + void GetClientCerts(const SSLCertRequestInfo& cert_request_info, + CertificateList* selected_certs, + const base::Closure& callback) override; protected: // ClientCertStoreNSS: - virtual void GetClientCertsImpl(CERTCertList* cert_list, - const SSLCertRequestInfo& request, - bool query_nssdb, - CertificateList* selected_certs) override; + void GetClientCertsImpl(CERTCertList* cert_list, + const SSLCertRequestInfo& request, + bool query_nssdb, + CertificateList* selected_certs) override; private: void CertFilterInitialized(const SSLCertRequestInfo* request,
diff --git a/net/test/spawned_test_server/local_test_server_win.cc b/net/test/spawned_test_server/local_test_server_win.cc index 5eb5aaf..71e1f7e 100644 --- a/net/test/spawned_test_server/local_test_server_win.cc +++ b/net/test/spawned_test_server/local_test_server_win.cc
@@ -78,60 +78,6 @@ return true; } -// Class that sets up a temporary path that includes the supplied path -// at the end. -// -// TODO(bratell): By making this more generic we can possibly reuse -// it at other places such as -// chrome/common/multi_process_lock_unittest.cc. -class ScopedPath { - public: - // Constructor which sets up the environment to include the path to - // |path_to_add|. - explicit ScopedPath(const base::FilePath& path_to_add); - - // Destructor that restores the path that were active when the - // object was constructed. - ~ScopedPath(); - - private: - // The PATH environment variable before it was changed or an empty - // string if there was no PATH environment variable. - std::string old_path_; - - // The helper object that allows us to read and set environment - // variables more easily. - scoped_ptr<base::Environment> environment_; - - // A flag saying if we have actually modified the environment. - bool path_modified_; - - DISALLOW_COPY_AND_ASSIGN(ScopedPath); -}; - -ScopedPath::ScopedPath(const base::FilePath& path_to_add) - : environment_(base::Environment::Create()), - path_modified_(false) { - environment_->GetVar("PATH", &old_path_); - - std::string new_value = old_path_; - if (!new_value.empty()) - new_value += ";"; - - new_value += base::WideToUTF8(path_to_add.value()); - - path_modified_ = environment_->SetVar("PATH", new_value); -} - -ScopedPath::~ScopedPath() { - if (!path_modified_) - return; - if (old_path_.empty()) - environment_->UnSetVar("PATH"); - else - environment_->SetVar("PATH", old_path_); -} - } // namespace namespace net {
diff --git a/net/tools/crash_cache/crash_cache.cc b/net/tools/crash_cache/crash_cache.cc index 60d7158..34eaafa 100644 --- a/net/tools/crash_cache/crash_cache.cc +++ b/net/tools/crash_cache/crash_cache.cc
@@ -84,12 +84,12 @@ NET_EXPORT_PRIVATE extern RankCrashes g_rankings_crash; } -const char* kCrashEntryName = "the first key"; +const char kCrashEntryName[] = "the first key"; // Creates the destinaton folder for this run, and returns it on full_path. bool CreateTargetFolder(const base::FilePath& path, RankCrashes action, base::FilePath* full_path) { - const char* folders[] = { + const char* const folders[] = { "", "insert_empty1", "insert_empty2",
diff --git a/net/tools/quic/end_to_end_test.cc b/net/tools/quic/end_to_end_test.cc index 1104528..fa9a8e7 100644 --- a/net/tools/quic/end_to_end_test.cc +++ b/net/tools/quic/end_to_end_test.cc
@@ -70,8 +70,8 @@ namespace test { namespace { -const char* kFooResponseBody = "Artichoke hearts make me happy."; -const char* kBarResponseBody = "Palm hearts are pretty delicious, also."; +const char kFooResponseBody[] = "Artichoke hearts make me happy."; +const char kBarResponseBody[] = "Palm hearts are pretty delicious, also."; // Run all tests with the cross products of all versions. struct TestParams { @@ -142,12 +142,9 @@ use_fec != 0, congestion_control_tag)); // Test client supporting all versions and server supporting 1 - // version. - // Simulate an old server and exercise version downgrade in the - // client. - // Protocol negotiation should occur. Skip the i = 0 case because it - // is - // essentially the same as the default case. + // version. Simulate an old server and exercise version downgrade in + // the client. Protocol negotiation should occur. Skip the i = 0 case + // because it is essentially the same as the default case. for (QuicVersion version : *client_versions) { QuicVersionVector server_supported_versions; server_supported_versions.push_back(version);
diff --git a/net/tools/quic/spdy_utils.cc b/net/tools/quic/spdy_utils.cc index c2b6174..2cfd381 100644 --- a/net/tools/quic/spdy_utils.cc +++ b/net/tools/quic/spdy_utils.cc
@@ -24,14 +24,14 @@ namespace net { namespace tools { -const char* const kV4Host = ":authority"; +const char kV4Host[] = ":authority"; -const char* const kV3Host = ":host"; -const char* const kV3Path = ":path"; -const char* const kV3Scheme = ":scheme"; -const char* const kV3Status = ":status"; -const char* const kV3Method = ":method"; -const char* const kV3Version = ":version"; +const char kV3Host[] = ":host"; +const char kV3Path[] = ":path"; +const char kV3Scheme[] = ":scheme"; +const char kV3Status[] = ":status"; +const char kV3Method[] = ":method"; +const char kV3Version[] = ":version"; void PopulateSpdyHeaderBlock(const BalsaHeaders& headers, SpdyHeaderBlock* block,
diff --git a/net/tools/quic/test_tools/http_message.cc b/net/tools/quic/test_tools/http_message.cc index 9bd3cffc..cb32255 100644 --- a/net/tools/quic/test_tools/http_message.cc +++ b/net/tools/quic/test_tools/http_message.cc
@@ -20,20 +20,20 @@ namespace { -//const char* kContentEncoding = "content-encoding"; -const char* kContentLength = "content-length"; -const char* kTransferCoding = "transfer-encoding"; +//const char kContentEncoding[] = "content-encoding"; +const char kContentLength[] = "content-length"; +const char kTransferCoding[] = "transfer-encoding"; // Both kHTTPVersionString and kMethodString arrays are constructed to match // the enum values defined in Version and Method of HTTPMessage. -const char* kHTTPVersionString[] = { +const char* const kHTTPVersionString[] = { "", "HTTP/0.9", "HTTP/1.0", "HTTP/1.1" }; -const char* kMethodString[] = { +const char* const kMethodString[] = { "", "OPTIONS", "GET",
diff --git a/net/tools/quic/test_tools/quic_test_client.cc b/net/tools/quic/test_tools/quic_test_client.cc index 97a0674..94d55b4 100644 --- a/net/tools/quic/test_tools/quic_test_client.cc +++ b/net/tools/quic/test_tools/quic_test_client.cc
@@ -255,9 +255,8 @@ scoped_ptr<BalsaHeaders> munged_headers(MungeHeaders(message.headers(), secure_)); ssize_t ret = GetOrCreateStream()->SendRequest( - munged_headers.get() ? *munged_headers.get() : *message.headers(), - message.body(), - message.has_complete_message()); + munged_headers.get() ? *munged_headers : *message.headers(), + message.body(), message.has_complete_message()); WaitForWriteToFlush(); return ret; }
diff --git a/net/udp/udp_socket_unittest.cc b/net/udp/udp_socket_unittest.cc index c92bf2b..221be01f 100644 --- a/net/udp/udp_socket_unittest.cc +++ b/net/udp/udp_socket_unittest.cc
@@ -541,7 +541,7 @@ TEST_F(UDPSocketTest, MAYBE_JoinMulticastGroup) { const uint16 kPort = 9999; - const char* const kGroup = "237.132.100.17"; + const char kGroup[] = "237.132.100.17"; IPEndPoint bind_address; CreateUDPAddress("0.0.0.0", kPort, &bind_address);
diff --git a/net/url_request/sdch_dictionary_fetcher.cc b/net/url_request/sdch_dictionary_fetcher.cc index 450a6082..b30f78ac 100644 --- a/net/url_request/sdch_dictionary_fetcher.cc +++ b/net/url_request/sdch_dictionary_fetcher.cc
@@ -60,6 +60,11 @@ attempted_load_.insert(dictionary_url); fetch_queue_.push(dictionary_url); + // If the loop is already processing, it'll pick up the above in the + // normal course of events. + if (next_state_ != STATE_NONE) + return; + next_state_ = STATE_IDLE; // There are no callbacks to user code from the dictionary fetcher,
diff --git a/net/url_request/sdch_dictionary_fetcher_unittest.cc b/net/url_request/sdch_dictionary_fetcher_unittest.cc index f79efc6..460fc5c4 100644 --- a/net/url_request/sdch_dictionary_fetcher_unittest.cc +++ b/net/url_request/sdch_dictionary_fetcher_unittest.cc
@@ -7,7 +7,7 @@ #include <string> #include "base/bind.h" -#include "base/message_loop/message_loop_proxy.h" +#include "base/callback.h" #include "base/run_loop.h" #include "base/strings/stringprintf.h" #include "base/thread_task_runner_handle.h" @@ -21,33 +21,19 @@ namespace net { -static const char* kSampleBufferContext = "This is a sample buffer."; -static const char* kTestDomain = "top.domain.test"; +namespace { + +const char kSampleBufferContext[] = "This is a sample buffer."; +const char kTestDomain[] = "top.domain.test"; class URLRequestSpecifiedResponseJob : public URLRequestSimpleJob { public: URLRequestSpecifiedResponseJob(URLRequest* request, - NetworkDelegate* network_delegate) - : URLRequestSimpleJob(request, network_delegate) {} - - static void AddUrlHandler() { - net::URLRequestFilter* filter = net::URLRequestFilter::GetInstance(); - jobs_requested_ = 0; - filter->AddHostnameHandler( - "http", kTestDomain, &URLRequestSpecifiedResponseJob::Factory); - } - - static void RemoveUrlHandler() { - net::URLRequestFilter* filter = net::URLRequestFilter::GetInstance(); - filter->RemoveHostnameHandler("http", kTestDomain); - jobs_requested_ = 0; - } - - static URLRequestJob* Factory(URLRequest* request, - net::NetworkDelegate* network_delegate, - const std::string& scheme) { - ++jobs_requested_; - return new URLRequestSpecifiedResponseJob(request, network_delegate); + NetworkDelegate* network_delegate, + const base::Closure& destruction_callback) + : URLRequestSimpleJob(request, network_delegate), + destruction_callback_(destruction_callback) { + DCHECK(!destruction_callback.is_null()); } static std::string ExpectedResponseForURL(const GURL& url) { @@ -57,13 +43,10 @@ url.spec().c_str()); } - static int jobs_requested() { return jobs_requested_; } - private: - ~URLRequestSpecifiedResponseJob() override{}; + ~URLRequestSpecifiedResponseJob() override { destruction_callback_.Run(); } // URLRequestSimpleJob implementation: - int GetData(std::string* mime_type, std::string* charset, std::string* data, @@ -73,14 +56,70 @@ return OK; } - base::TaskRunner* GetTaskRunner() const override { - return base::MessageLoopProxy::current().get(); - } - - static int jobs_requested_; + const base::Closure destruction_callback_; }; -int URLRequestSpecifiedResponseJob::jobs_requested_(0); +class SpecifiedResponseJobInterceptor : public URLRequestInterceptor { + public: + // A callback to be called whenever a URLRequestSpecifiedResponseJob is + // created or destroyed. The argument will be the change in number of + // jobs (i.e. +1 for created, -1 for destroyed). + typedef base::Callback<void(int outstanding_job_delta)> LifecycleCallback; + + explicit SpecifiedResponseJobInterceptor( + const LifecycleCallback& lifecycle_callback) + : lifecycle_callback_(lifecycle_callback), factory_(this) { + DCHECK(!lifecycle_callback_.is_null()); + } + ~SpecifiedResponseJobInterceptor() override {} + + URLRequestJob* MaybeInterceptRequest( + URLRequest* request, + NetworkDelegate* network_delegate) const override { + if (!lifecycle_callback_.is_null()) + lifecycle_callback_.Run(1); + + return new URLRequestSpecifiedResponseJob( + request, network_delegate, base::Bind(lifecycle_callback_, -1)); + } + + // The caller must ensure that the callback is valid to call for the + // lifetime of the SpecifiedResponseJobInterceptor (i.e. until + // Unregister() is called). + static void RegisterWithFilter(const LifecycleCallback& lifecycle_callback) { + scoped_ptr<SpecifiedResponseJobInterceptor> interceptor( + new SpecifiedResponseJobInterceptor(lifecycle_callback)); + + net::URLRequestFilter::GetInstance()->AddHostnameInterceptor( + "http", kTestDomain, interceptor.Pass()); + } + + static void Unregister() { + net::URLRequestFilter::GetInstance()->RemoveHostnameHandler("http", + kTestDomain); + } + + private: + void OnSpecfiedResponseJobDestruction() const { + if (!lifecycle_callback_.is_null()) + lifecycle_callback_.Run(-1); + } + + LifecycleCallback lifecycle_callback_; + mutable base::WeakPtrFactory<SpecifiedResponseJobInterceptor> factory_; +}; + +// Local test infrastructure +// * URLRequestSpecifiedResponseJob: A URLRequestJob that returns +// a different but derivable response for each URL (used for all +// url requests in this file). The class provides interfaces to +// signal whenever the total number of jobs transitions to zero. +// * SdchDictionaryFetcherTest: Registers a callback with the above +// class, and provides blocking interfaces for a transition to zero jobs. +// Contains an SdchDictionaryFetcher, and tracks fetcher dictionary +// addition callbacks. +// Most tests schedule a dictionary fetch, wait for no jobs outstanding, +// then test that the fetch results are as expected. class SdchDictionaryFetcherTest : public ::testing::Test { public: @@ -93,17 +132,22 @@ GURL dictionary_url; }; - SdchDictionaryFetcherTest() { - URLRequestSpecifiedResponseJob::AddUrlHandler(); - context_.reset(new TestURLRequestContext); - fetcher_.reset(new SdchDictionaryFetcher( - context_.get(), - base::Bind(&SdchDictionaryFetcherTest::OnDictionaryFetched, - base::Unretained(this)))); + SdchDictionaryFetcherTest() + : jobs_requested_(0), + jobs_outstanding_(0), + context_(new TestURLRequestContext), + fetcher_(new SdchDictionaryFetcher( + context_.get(), + base::Bind(&SdchDictionaryFetcherTest::OnDictionaryFetched, + base::Unretained(this)))), + factory_(this) { + SpecifiedResponseJobInterceptor::RegisterWithFilter( + base::Bind(&SdchDictionaryFetcherTest::OnNumberJobsChanged, + factory_.GetWeakPtr())); } ~SdchDictionaryFetcherTest() override { - URLRequestSpecifiedResponseJob::RemoveUrlHandler(); + SpecifiedResponseJobInterceptor::Unregister(); } void OnDictionaryFetched(const std::string& dictionary_text, @@ -113,6 +157,8 @@ DictionaryAdditions(dictionary_text, dictionary_url)); } + // Return (in |*out|) all dictionary additions since the last time + // this function was called. void GetDictionaryAdditions(std::vector<DictionaryAdditions>* out) { out->swap(dictionary_additions); dictionary_additions.clear(); @@ -121,9 +167,7 @@ SdchDictionaryFetcher* fetcher() { return fetcher_.get(); } // May not be called outside the SetUp()/TearDown() interval. - int JobsRequested() { - return URLRequestSpecifiedResponseJob::jobs_requested(); - } + int jobs_requested() const { return jobs_requested_; } GURL PathToGurl(const char* path) { std::string gurl_string("http://"); @@ -133,19 +177,41 @@ return GURL(gurl_string); } + // Block until there are no outstanding URLRequestSpecifiedResponseJobs. + void WaitForNoJobs() { + if (jobs_outstanding_ == 0) + return; + + run_loop_.reset(new base::RunLoop); + run_loop_->Run(); + run_loop_.reset(); + } + private: + void OnNumberJobsChanged(int outstanding_jobs_delta) { + if (outstanding_jobs_delta > 0) + jobs_requested_ += outstanding_jobs_delta; + jobs_outstanding_ += outstanding_jobs_delta; + if (jobs_outstanding_ == 0 && run_loop_) + run_loop_->Quit(); + } + + int jobs_requested_; + int jobs_outstanding_; + scoped_ptr<base::RunLoop> run_loop_; scoped_ptr<TestURLRequestContext> context_; scoped_ptr<SdchDictionaryFetcher> fetcher_; std::vector<DictionaryAdditions> dictionary_additions; + base::WeakPtrFactory<SdchDictionaryFetcherTest> factory_; }; // Schedule a fetch and make sure it happens. TEST_F(SdchDictionaryFetcherTest, Basic) { GURL dictionary_url(PathToGurl("dictionary")); fetcher()->Schedule(dictionary_url); + WaitForNoJobs(); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(1, JobsRequested()); + EXPECT_EQ(1, jobs_requested()); std::vector<DictionaryAdditions> additions; GetDictionaryAdditions(&additions); ASSERT_EQ(1u, additions.size()); @@ -160,9 +226,9 @@ fetcher()->Schedule(dictionary_url); fetcher()->Schedule(dictionary_url); fetcher()->Schedule(dictionary_url); - base::RunLoop().RunUntilIdle(); + WaitForNoJobs(); - EXPECT_EQ(1, JobsRequested()); + EXPECT_EQ(1, jobs_requested()); std::vector<DictionaryAdditions> additions; GetDictionaryAdditions(&additions); ASSERT_EQ(1u, additions.size()); @@ -181,9 +247,33 @@ fetcher()->Schedule(dictionary_url_2); fetcher()->Schedule(dictionary_url_3); fetcher()->Cancel(); - base::RunLoop().RunUntilIdle(); + WaitForNoJobs(); // Synchronous execution may have resulted in a single job being scheduled. - EXPECT_GE(1, JobsRequested()); + EXPECT_GE(1, jobs_requested()); } + +// Attempt to confuse the fetcher loop processing by scheduling a +// dictionary addition while another fetch is in process. +TEST_F(SdchDictionaryFetcherTest, LoopRace) { + GURL dictionary0_url(PathToGurl("dictionary0")); + GURL dictionary1_url(PathToGurl("dictionary1")); + fetcher()->Schedule(dictionary0_url); + fetcher()->Schedule(dictionary1_url); + WaitForNoJobs(); + + ASSERT_EQ(2, jobs_requested()); + std::vector<DictionaryAdditions> additions; + GetDictionaryAdditions(&additions); + ASSERT_EQ(2u, additions.size()); + EXPECT_EQ( + URLRequestSpecifiedResponseJob::ExpectedResponseForURL(dictionary0_url), + additions[0].dictionary_text); + EXPECT_EQ( + URLRequestSpecifiedResponseJob::ExpectedResponseForURL(dictionary1_url), + additions[1].dictionary_text); } + +} // namespace + +} // namespace net
diff --git a/net/websockets/websocket_end_to_end_test.cc b/net/websockets/websocket_end_to_end_test.cc new file mode 100644 index 0000000..0b5944f --- /dev/null +++ b/net/websockets/websocket_end_to_end_test.cc
@@ -0,0 +1,370 @@ +// 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. + +// End-to-end tests for WebSocket. +// +// A python server is (re)started for each test, which is moderately +// inefficient. However, it makes these tests a good fit for scenarios which +// require special server configurations. + +#include <string> + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/callback.h" +#include "base/memory/scoped_ptr.h" +#include "base/message_loop/message_loop.h" +#include "base/run_loop.h" +#include "net/base/auth.h" +#include "net/base/network_delegate.h" +#include "net/base/test_data_directory.h" +#include "net/proxy/proxy_service.h" +#include "net/test/spawned_test_server/spawned_test_server.h" +#include "net/url_request/url_request_test_util.h" +#include "net/websockets/websocket_channel.h" +#include "net/websockets/websocket_event_interface.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "url/origin.h" + +namespace net { + +namespace { + +static const char kEchoServer[] = "echo-with-no-extension"; + +// An implementation of WebSocketEventInterface that waits for and records the +// results of the connect. +class ConnectTestingEventInterface : public WebSocketEventInterface { + public: + ConnectTestingEventInterface(); + + void WaitForResponse(); + + bool failed() const { return failed_; } + + // Only set if the handshake failed, otherwise empty. + std::string failure_message() const; + + std::string selected_subprotocol() const; + + std::string extensions() const; + + // Implementation of WebSocketEventInterface. + ChannelState OnAddChannelResponse(bool fail, + const std::string& selected_subprotocol, + const std::string& extensions) override; + + ChannelState OnDataFrame(bool fin, + WebSocketMessageType type, + const std::vector<char>& data) override; + + ChannelState OnFlowControl(int64 quota) override; + + ChannelState OnClosingHandshake() override; + + ChannelState OnDropChannel(bool was_clean, + uint16 code, + const std::string& reason) override; + + ChannelState OnFailChannel(const std::string& message) override; + + ChannelState OnStartOpeningHandshake( + scoped_ptr<WebSocketHandshakeRequestInfo> request) override; + + ChannelState OnFinishOpeningHandshake( + scoped_ptr<WebSocketHandshakeResponseInfo> response) override; + + ChannelState OnSSLCertificateError( + scoped_ptr<SSLErrorCallbacks> ssl_error_callbacks, + const GURL& url, + const SSLInfo& ssl_info, + bool fatal) override; + + private: + void QuitNestedEventLoop(); + + // failed_ is true if the handshake failed (ie. OnFailChannel was called). + bool failed_; + std::string selected_subprotocol_; + std::string extensions_; + std::string failure_message_; + base::RunLoop run_loop_; + + DISALLOW_COPY_AND_ASSIGN(ConnectTestingEventInterface); +}; + +ConnectTestingEventInterface::ConnectTestingEventInterface() : failed_(true) { +} + +void ConnectTestingEventInterface::WaitForResponse() { + run_loop_.Run(); +} + +std::string ConnectTestingEventInterface::failure_message() const { + return failure_message_; +} + +std::string ConnectTestingEventInterface::selected_subprotocol() const { + return selected_subprotocol_; +} + +std::string ConnectTestingEventInterface::extensions() const { + return extensions_; +} + +// Make the function definitions below less verbose. +typedef ConnectTestingEventInterface::ChannelState ChannelState; + +ChannelState ConnectTestingEventInterface::OnAddChannelResponse( + bool fail, + const std::string& selected_subprotocol, + const std::string& extensions) { + failed_ = fail; + selected_subprotocol_ = selected_subprotocol; + extensions_ = extensions; + QuitNestedEventLoop(); + return fail ? CHANNEL_DELETED : CHANNEL_ALIVE; +} + +ChannelState ConnectTestingEventInterface::OnDataFrame( + bool fin, + WebSocketMessageType type, + const std::vector<char>& data) { + return CHANNEL_ALIVE; +} + +ChannelState ConnectTestingEventInterface::OnFlowControl(int64 quota) { + return CHANNEL_ALIVE; +} + +ChannelState ConnectTestingEventInterface::OnClosingHandshake() { + return CHANNEL_ALIVE; +} + +ChannelState ConnectTestingEventInterface::OnDropChannel( + bool was_clean, + uint16 code, + const std::string& reason) { + return CHANNEL_DELETED; +} + +ChannelState ConnectTestingEventInterface::OnFailChannel( + const std::string& message) { + failed_ = true; + failure_message_ = message; + QuitNestedEventLoop(); + return CHANNEL_DELETED; +} + +ChannelState ConnectTestingEventInterface::OnStartOpeningHandshake( + scoped_ptr<WebSocketHandshakeRequestInfo> request) { + return CHANNEL_ALIVE; +} + +ChannelState ConnectTestingEventInterface::OnFinishOpeningHandshake( + scoped_ptr<WebSocketHandshakeResponseInfo> response) { + return CHANNEL_ALIVE; +} + +ChannelState ConnectTestingEventInterface::OnSSLCertificateError( + scoped_ptr<SSLErrorCallbacks> ssl_error_callbacks, + const GURL& url, + const SSLInfo& ssl_info, + bool fatal) { + base::MessageLoop::current()->PostTask( + FROM_HERE, base::Bind(&SSLErrorCallbacks::CancelSSLRequest, + base::Owned(ssl_error_callbacks.release()), + ERR_SSL_PROTOCOL_ERROR, &ssl_info)); + return CHANNEL_ALIVE; +} + +void ConnectTestingEventInterface::QuitNestedEventLoop() { + run_loop_.Quit(); +} + +// A subclass of TestNetworkDelegate that additionally implements the +// OnResolveProxy callback and records the information passed to it. +class TestNetworkDelegateWithProxyInfo : public TestNetworkDelegate { + public: + TestNetworkDelegateWithProxyInfo() {} + + struct ResolvedProxyInfo { + GURL url; + ProxyInfo proxy_info; + }; + + const ResolvedProxyInfo& resolved_proxy_info() const { + return resolved_proxy_info_; + } + + protected: + void OnResolveProxy(const GURL& url, + int load_flags, + const ProxyService& proxy_service, + ProxyInfo* result) override { + resolved_proxy_info_.url = url; + resolved_proxy_info_.proxy_info = *result; + } + + private: + ResolvedProxyInfo resolved_proxy_info_; + + DISALLOW_COPY_AND_ASSIGN(TestNetworkDelegateWithProxyInfo); +}; + +class WebSocketEndToEndTest : public ::testing::Test { + protected: + WebSocketEndToEndTest() + : event_interface_(new ConnectTestingEventInterface), + network_delegate_(new TestNetworkDelegateWithProxyInfo), + context_(true), + channel_(make_scoped_ptr(event_interface_), &context_), + initialised_context_(false) {} + + // Initialise the URLRequestContext. Normally done automatically by + // ConnectAndWait(). This method is for the use of tests that need the + // URLRequestContext initialised before calling ConnectAndWait(). + void InitialiseContext() { + context_.set_network_delegate(network_delegate_.get()); + context_.Init(); + initialised_context_ = true; + } + + // Send the connect request to |socket_url| and wait for a response. Returns + // true if the handshake succeeded. + bool ConnectAndWait(const GURL& socket_url) { + if (!initialised_context_) { + InitialiseContext(); + } + std::vector<std::string> sub_protocols; + url::Origin origin("http://localhost"); + channel_.SendAddChannelRequest(GURL(socket_url), sub_protocols, origin); + event_interface_->WaitForResponse(); + return !event_interface_->failed(); + } + + ConnectTestingEventInterface* event_interface_; // owned by channel_ + scoped_ptr<TestNetworkDelegateWithProxyInfo> network_delegate_; + TestURLRequestContext context_; + WebSocketChannel channel_; + bool initialised_context_; +}; + +// None of these tests work on Android. +// TODO(ricea): Make these tests work on Android. See crbug.com/441711. +#if defined(OS_ANDROID) +#define DISABLED_ON_ANDROID(test) DISABLED_##test +#else +#define DISABLED_ON_ANDROID(test) test +#endif + +// Basic test of connectivity. If this test fails, nothing else can be expected +// to work. +TEST_F(WebSocketEndToEndTest, DISABLED_ON_ANDROID(BasicSmokeTest)) { + SpawnedTestServer ws_server(SpawnedTestServer::TYPE_WS, + SpawnedTestServer::kLocalhost, + GetWebSocketTestDataDirectory()); + ASSERT_TRUE(ws_server.Start()); + EXPECT_TRUE(ConnectAndWait(ws_server.GetURL(kEchoServer))); +} + +// Test for issue crbug.com/433695 "Unencrypted WebSocket connection via +// authenticated proxy times out" +// TODO(ricea): Enable this when the issue is fixed. +TEST_F(WebSocketEndToEndTest, DISABLED_HttpsProxyUnauthedFails) { + SpawnedTestServer proxy_server(SpawnedTestServer::TYPE_BASIC_AUTH_PROXY, + SpawnedTestServer::kLocalhost, + base::FilePath()); + SpawnedTestServer ws_server(SpawnedTestServer::TYPE_WS, + SpawnedTestServer::kLocalhost, + GetWebSocketTestDataDirectory()); + ASSERT_TRUE(proxy_server.StartInBackground()); + ASSERT_TRUE(ws_server.StartInBackground()); + ASSERT_TRUE(proxy_server.BlockUntilStarted()); + ASSERT_TRUE(ws_server.BlockUntilStarted()); + std::string proxy_config = + "https=" + proxy_server.host_port_pair().ToString(); + scoped_ptr<ProxyService> proxy_service( + ProxyService::CreateFixed(proxy_config)); + ASSERT_TRUE(proxy_service); + context_.set_proxy_service(proxy_service.get()); + EXPECT_FALSE(ConnectAndWait(ws_server.GetURL(kEchoServer))); + EXPECT_EQ("Proxy authentication failed", event_interface_->failure_message()); +} + +TEST_F(WebSocketEndToEndTest, DISABLED_ON_ANDROID(HttpsWssProxyUnauthedFails)) { + SpawnedTestServer proxy_server(SpawnedTestServer::TYPE_BASIC_AUTH_PROXY, + SpawnedTestServer::kLocalhost, + base::FilePath()); + SpawnedTestServer wss_server(SpawnedTestServer::TYPE_WSS, + SpawnedTestServer::kLocalhost, + GetWebSocketTestDataDirectory()); + ASSERT_TRUE(proxy_server.StartInBackground()); + ASSERT_TRUE(wss_server.StartInBackground()); + ASSERT_TRUE(proxy_server.BlockUntilStarted()); + ASSERT_TRUE(wss_server.BlockUntilStarted()); + std::string proxy_config = + "https=" + proxy_server.host_port_pair().ToString(); + scoped_ptr<ProxyService> proxy_service( + ProxyService::CreateFixed(proxy_config)); + ASSERT_TRUE(proxy_service); + context_.set_proxy_service(proxy_service.get()); + EXPECT_FALSE(ConnectAndWait(wss_server.GetURL(kEchoServer))); + EXPECT_EQ("Proxy authentication failed", event_interface_->failure_message()); +} + +// Regression test for crbug/426736 "WebSocket connections not using configured +// system HTTPS Proxy". +TEST_F(WebSocketEndToEndTest, DISABLED_ON_ANDROID(HttpsProxyUsed)) { + SpawnedTestServer proxy_server(SpawnedTestServer::TYPE_BASIC_AUTH_PROXY, + SpawnedTestServer::kLocalhost, + base::FilePath()); + SpawnedTestServer ws_server(SpawnedTestServer::TYPE_WS, + SpawnedTestServer::kLocalhost, + GetWebSocketTestDataDirectory()); + ASSERT_TRUE(proxy_server.StartInBackground()); + ASSERT_TRUE(ws_server.StartInBackground()); + ASSERT_TRUE(proxy_server.BlockUntilStarted()); + ASSERT_TRUE(ws_server.BlockUntilStarted()); + std::string proxy_config = "https=" + + proxy_server.host_port_pair().ToString() + ";" + + "http=" + proxy_server.host_port_pair().ToString(); + scoped_ptr<ProxyService> proxy_service( + ProxyService::CreateFixed(proxy_config)); + context_.set_proxy_service(proxy_service.get()); + InitialiseContext(); + + // The test server doesn't have an unauthenticated proxy mode. WebSockets + // cannot provide auth information that isn't already cached, so it's + // necessary to preflight an HTTP request to authenticate against the proxy. + std::string scheme("http"); + GURL::Replacements replacements; + replacements.SetSchemeStr(scheme); + // It doesn't matter what the URL is, as long as it is an HTTP navigation. + GURL http_page = + ws_server.GetURL("connect_check.html").ReplaceComponents(replacements); + TestDelegate delegate; + delegate.set_credentials( + AuthCredentials(base::ASCIIToUTF16("foo"), base::ASCIIToUTF16("bar"))); + { + scoped_ptr<URLRequest> request( + context_.CreateRequest(http_page, DEFAULT_PRIORITY, &delegate, NULL)); + request->Start(); + // TestDelegate exits the message loop when the request completes by + // default. + base::RunLoop().Run(); + EXPECT_TRUE(delegate.auth_required_called()); + } + + GURL ws_url = ws_server.GetURL(kEchoServer); + EXPECT_TRUE(ConnectAndWait(ws_url)); + const TestNetworkDelegateWithProxyInfo::ResolvedProxyInfo& info = + network_delegate_->resolved_proxy_info(); + EXPECT_EQ(ws_url, info.url); + EXPECT_TRUE(info.proxy_info.is_http()); +} + +} // namespace + +} // namespace net
diff --git a/net/websockets/websocket_extension_parser_test.cc b/net/websockets/websocket_extension_parser_test.cc index dc7dc85..c19460cb 100644 --- a/net/websockets/websocket_extension_parser_test.cc +++ b/net/websockets/websocket_extension_parser_test.cc
@@ -65,7 +65,7 @@ } TEST(WebSocketExtensionParserTest, InvalidPatterns) { - const char* patterns[] = { + const char* const patterns[] = { "fo\ao", // control in extension name "fo\x01o", // control in extension name "fo<o", // separator in extension name
diff --git a/net/websockets/websocket_handshake_constants.cc b/net/websockets/websocket_handshake_constants.cc index dc670aa..bb031e21 100644 --- a/net/websockets/websocket_handshake_constants.cc +++ b/net/websockets/websocket_handshake_constants.cc
@@ -7,32 +7,32 @@ namespace net { namespace websockets { -const char* const kHttpProtocolVersion = "HTTP/1.1"; +const char kHttpProtocolVersion[] = "HTTP/1.1"; const size_t kRawChallengeLength = 16; -const char* const kSecWebSocketProtocol = "Sec-WebSocket-Protocol"; -const char* const kSecWebSocketExtensions = "Sec-WebSocket-Extensions"; -const char* const kSecWebSocketKey = "Sec-WebSocket-Key"; -const char* const kSecWebSocketAccept = "Sec-WebSocket-Accept"; -const char* const kSecWebSocketVersion = "Sec-WebSocket-Version"; +const char kSecWebSocketProtocol[] = "Sec-WebSocket-Protocol"; +const char kSecWebSocketExtensions[] = "Sec-WebSocket-Extensions"; +const char kSecWebSocketKey[] = "Sec-WebSocket-Key"; +const char kSecWebSocketAccept[] = "Sec-WebSocket-Accept"; +const char kSecWebSocketVersion[] = "Sec-WebSocket-Version"; -const char* const kSupportedVersion = "13"; +const char kSupportedVersion[] = "13"; -const char* const kUpgrade = "Upgrade"; -const char* const kWebSocketGuid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; +const char kUpgrade[] = "Upgrade"; +const char kWebSocketGuid[] = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; -const char* const kSecWebSocketProtocolSpdy3 = ":sec-websocket-protocol"; -const char* const kSecWebSocketExtensionsSpdy3 = ":sec-websocket-extensions"; +const char kSecWebSocketProtocolSpdy3[] = ":sec-websocket-protocol"; +const char kSecWebSocketExtensionsSpdy3[] = ":sec-websocket-extensions"; const char* const kSecWebSocketProtocolLowercase = kSecWebSocketProtocolSpdy3 + 1; const char* const kSecWebSocketExtensionsLowercase = kSecWebSocketExtensionsSpdy3 + 1; -const char* const kSecWebSocketKeyLowercase = "sec-websocket-key"; -const char* const kSecWebSocketVersionLowercase = "sec-websocket-version"; -const char* const kUpgradeLowercase = "upgrade"; -const char* const kWebSocketLowercase = "websocket"; +const char kSecWebSocketKeyLowercase[] = "sec-websocket-key"; +const char kSecWebSocketVersionLowercase[] = "sec-websocket-version"; +const char kUpgradeLowercase[] = "upgrade"; +const char kWebSocketLowercase[] = "websocket"; } // namespace websockets } // namespace net
diff --git a/net/websockets/websocket_handshake_constants.h b/net/websockets/websocket_handshake_constants.h index 43d3efd..d68a28a 100644 --- a/net/websockets/websocket_handshake_constants.h +++ b/net/websockets/websocket_handshake_constants.h
@@ -22,45 +22,45 @@ // "HTTP/1.1" // RFC6455 only requires HTTP/1.1 "or better" but in practice an HTTP version // other than 1.1 should not occur in a WebSocket handshake. -extern const char* const kHttpProtocolVersion; +extern const char kHttpProtocolVersion[]; // The Sec-WebSockey-Key challenge is 16 random bytes, base64 encoded. extern const size_t kRawChallengeLength; // "Sec-WebSocket-Protocol" -extern const char* const kSecWebSocketProtocol; +extern const char kSecWebSocketProtocol[]; // "Sec-WebSocket-Extensions" -extern const char* const kSecWebSocketExtensions; +extern const char kSecWebSocketExtensions[]; // "Sec-WebSocket-Key" -extern const char* const kSecWebSocketKey; +extern const char kSecWebSocketKey[]; // "Sec-WebSocket-Accept" -extern const char* const kSecWebSocketAccept; +extern const char kSecWebSocketAccept[]; // "Sec-WebSocket-Version" -extern const char* const kSecWebSocketVersion; +extern const char kSecWebSocketVersion[]; // This implementation only supports one version of the WebSocket protocol, // "13", as specified in RFC6455. If support for multiple versions is added in // future, it will probably no longer be worth having a constant for this. -extern const char* const kSupportedVersion; +extern const char kSupportedVersion[]; // "Upgrade" -extern const char* const kUpgrade; +extern const char kUpgrade[]; // "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" as defined in section 4.1 of // RFC6455. -extern const char* const kWebSocketGuid; +extern const char kWebSocketGuid[]; // Colon-prefixed lowercase headers for SPDY3. // ":sec-websocket-protocol" -extern const char* const kSecWebSocketProtocolSpdy3; +extern const char kSecWebSocketProtocolSpdy3[]; // ":sec-websocket-extensions" -extern const char* const kSecWebSocketExtensionsSpdy3; +extern const char kSecWebSocketExtensionsSpdy3[]; // Some parts of the code require lowercase versions of the header names in // order to do case-insensitive comparisons, or because of SPDY. @@ -71,17 +71,17 @@ extern const char* const kSecWebSocketExtensionsLowercase; // "sec-webSocket-key" -extern const char* const kSecWebSocketKeyLowercase; +extern const char kSecWebSocketKeyLowercase[]; // "sec-websocket-version" -extern const char* const kSecWebSocketVersionLowercase; +extern const char kSecWebSocketVersionLowercase[]; // "upgrade" -extern const char* const kUpgradeLowercase; +extern const char kUpgradeLowercase[]; // "websocket", as used in the "Upgrade:" header. This is always lowercase // (except in obsolete versions of the protocol). -extern const char* const kWebSocketLowercase; +extern const char kWebSocketLowercase[]; } // namespace websockets } // namespace net
diff --git a/net/websockets/websocket_stream_test.cc b/net/websockets/websocket_stream_test.cc index 03a593de..0fdc34b 100644 --- a/net/websockets/websocket_stream_test.cc +++ b/net/websockets/websocket_stream_test.cc
@@ -107,6 +107,12 @@ class WebSocketStreamCreateTest : public ::testing::Test { public: WebSocketStreamCreateTest() : has_failed_(false), ssl_fatal_(false) {} + ~WebSocketStreamCreateTest() override { + // Permit any endpoint locks to be released. + stream_request_.reset(); + stream_.reset(); + RunUntilIdle(); + } void CreateAndConnectCustomResponse( const std::string& socket_url, @@ -248,6 +254,7 @@ SSLInfo ssl_info_; bool ssl_fatal_; ScopedVector<SSLSocketDataProvider> ssl_data_; + ScopedWebSocketEndpointZeroUnlockDelay zero_unlock_delay_; }; // There are enough tests of the Sec-WebSocket-Extensions header that they
diff --git a/pdf/pdfium/pdfium_engine.cc b/pdf/pdfium/pdfium_engine.cc index 86485e0..cb323bb 100644 --- a/pdf/pdfium/pdfium_engine.cc +++ b/pdf/pdfium/pdfium_engine.cc
@@ -1052,6 +1052,10 @@ pp::ImageData* image_data, std::vector<pp::Rect>* ready, std::vector<pp::Rect>* pending) { + DCHECK(image_data); + DCHECK(ready); + DCHECK(pending); + pp::Rect leftover = rect; for (size_t i = 0; i < visible_pages_.size(); ++i) { int index = visible_pages_[i]; @@ -1070,15 +1074,18 @@ if (pages_[index]->available()) { int progressive = GetProgressiveIndex(index); - if (progressive != -1 && - progressive_paints_[progressive].rect != dirty_in_screen) { - // The PDFium code can only handle one progressive paint at a time, so - // queue this up. Previously we used to merge the rects when this - // happened, but it made scrolling up on complex PDFs very slow since - // there would be a damaged rect at the top (from scroll) and at the - // bottom (from toolbar). - pending->push_back(dirty_in_screen); - continue; + if (progressive != -1) { + DCHECK_GE(progressive, 0); + DCHECK_LT(static_cast<size_t>(progressive), progressive_paints_.size()); + if (progressive_paints_[progressive].rect != dirty_in_screen) { + // The PDFium code can only handle one progressive paint at a time, so + // queue this up. Previously we used to merge the rects when this + // happened, but it made scrolling up on complex PDFs very slow since + // there would be a damaged rect at the top (from scroll) and at the + // bottom (from toolbar). + pending->push_back(dirty_in_screen); + continue; + } } if (progressive == -1) { @@ -2341,7 +2348,7 @@ (permissions_ & kPDFPermissionPrintHighQualityMask) != 0; default: return true; - }; + } } void PDFiumEngine::SelectAll() { @@ -2359,7 +2366,6 @@ return pages_.size(); } - pp::VarArray PDFiumEngine::GetBookmarks() { pp::VarDictionary dict = TraverseBookmarks(doc_, NULL); // The root bookmark contains no useful information. @@ -2838,36 +2844,45 @@ bool PDFiumEngine::ContinuePaint(int progressive_index, pp::ImageData* image_data) { + DCHECK_GE(progressive_index, 0); + DCHECK_LT(static_cast<size_t>(progressive_index), progressive_paints_.size()); + DCHECK(image_data); + #if defined(OS_LINUX) g_last_instance_id = client_->GetPluginInstance()->pp_instance(); #endif int rv; + FPDF_BITMAP bitmap = progressive_paints_[progressive_index].bitmap; int page_index = progressive_paints_[progressive_index].page_index; + DCHECK_GE(page_index, 0); + DCHECK_LT(static_cast<size_t>(page_index), pages_.size()); + FPDF_PAGE page = pages_[page_index]->GetPage(); + last_progressive_start_time_ = base::Time::Now(); - if (progressive_paints_[progressive_index].bitmap) { - rv = FPDF_RenderPage_Continue( - pages_[page_index]->GetPage(), static_cast<IFSDK_PAUSE*>(this)); + if (bitmap) { + rv = FPDF_RenderPage_Continue(page, static_cast<IFSDK_PAUSE*>(this)); } else { pp::Rect dirty = progressive_paints_[progressive_index].rect; - progressive_paints_[progressive_index].bitmap = CreateBitmap(dirty, - image_data); + bitmap = CreateBitmap(dirty, image_data); int start_x, start_y, size_x, size_y; - GetPDFiumRect( - page_index, dirty, &start_x, &start_y, &size_x, &size_y); - FPDFBitmap_FillRect(progressive_paints_[progressive_index].bitmap, start_x, - start_y, size_x, size_y, 0xFFFFFFFF); + GetPDFiumRect(page_index, dirty, &start_x, &start_y, &size_x, &size_y); + FPDFBitmap_FillRect(bitmap, start_x, start_y, size_x, size_y, 0xFFFFFFFF); rv = FPDF_RenderPageBitmap_Start( - progressive_paints_[progressive_index].bitmap, - pages_[page_index]->GetPage(), start_x, start_y, size_x, size_y, + bitmap, page, start_x, start_y, size_x, size_y, current_rotation_, GetRenderingFlags(), static_cast<IFSDK_PAUSE*>(this)); + progressive_paints_[progressive_index].bitmap = bitmap; } return rv != FPDF_RENDER_TOBECOUNTINUED; } void PDFiumEngine::FinishPaint(int progressive_index, pp::ImageData* image_data) { + DCHECK_GE(progressive_index, 0); + DCHECK_LT(static_cast<size_t>(progressive_index), progressive_paints_.size()); + DCHECK(image_data); + int page_index = progressive_paints_[progressive_index].page_index; pp::Rect dirty_in_screen = progressive_paints_[progressive_index].rect; FPDF_BITMAP bitmap = progressive_paints_[progressive_index].bitmap; @@ -2903,6 +2918,9 @@ } void PDFiumEngine::FillPageSides(int progressive_index) { + DCHECK_GE(progressive_index, 0); + DCHECK_LT(static_cast<size_t>(progressive_index), progressive_paints_.size()); + int page_index = progressive_paints_[progressive_index].page_index; pp::Rect dirty_in_screen = progressive_paints_[progressive_index].rect; FPDF_BITMAP bitmap = progressive_paints_[progressive_index].bitmap; @@ -2949,6 +2967,10 @@ void PDFiumEngine::PaintPageShadow(int progressive_index, pp::ImageData* image_data) { + DCHECK_GE(progressive_index, 0); + DCHECK_LT(static_cast<size_t>(progressive_index), progressive_paints_.size()); + DCHECK(image_data); + int page_index = progressive_paints_[progressive_index].page_index; pp::Rect dirty_in_screen = progressive_paints_[progressive_index].rect; pp::Rect page_rect = pages_[page_index]->rect(); @@ -2973,6 +2995,10 @@ void PDFiumEngine::DrawSelections(int progressive_index, pp::ImageData* image_data) { + DCHECK_GE(progressive_index, 0); + DCHECK_LT(static_cast<size_t>(progressive_index), progressive_paints_.size()); + DCHECK(image_data); + int page_index = progressive_paints_[progressive_index].page_index; pp::Rect dirty_in_screen = progressive_paints_[progressive_index].rect;
diff --git a/pdf/pdfium/pdfium_engine.h b/pdf/pdfium/pdfium_engine.h index bf3bff9..d7b4835 100644 --- a/pdf/pdfium/pdfium_engine.h +++ b/pdf/pdfium/pdfium_engine.h
@@ -691,7 +691,7 @@ int page_index; // Temporary used to figure out if in a series of Paint() calls whether this // pending paint was updated or not. - int painted_; + bool painted_; }; std::vector<ProgressivePaint> progressive_paints_; @@ -708,6 +708,8 @@ // Set to true if the user is being prompted for their password. Will be set // to false after the user finishes getting their password. bool getting_password_; + + DISALLOW_COPY_AND_ASSIGN(PDFiumEngine); }; // Create a local variable of this when calling PDFium functions which can call
diff --git a/ppapi/api/private/ppb_nacl_private.idl b/ppapi/api/private/ppb_nacl_private.idl index fd6a7c7b..37c1155b 100644 --- a/ppapi/api/private/ppb_nacl_private.idl +++ b/ppapi/api/private/ppb_nacl_private.idl
@@ -168,8 +168,7 @@ interface PPB_NaCl_Private { /* Launches NaCl's sel_ldr process. Returns PP_EXTERNAL_PLUGIN_OK on success * and writes a NaClHandle to imc_handle. Returns PP_EXTERNAL_PLUGIN_FAILED on - * failure. The |enable_ppapi_dev| parameter controls whether GetInterface - * returns 'Dev' interfaces to the NaCl plugin. + * failure. * The |nexe_file_info| is currently used only in non-SFI mode. It is the * file handle for the main nexe file, which should be initially loaded. * LaunchSelLdr takes the ownership of the file handle. @@ -181,7 +180,6 @@ [in] str_t alleged_url, [in] PP_NaClFileInfo nexe_file_info, [in] PP_Bool uses_nonsfi_mode, - [in] PP_Bool enable_ppapi_dev, [in] PP_NaClAppProcessType process_type, [out] mem_t imc_handle, [in] PP_CompletionCallback callback); @@ -243,11 +241,6 @@ [in] uint64_t loaded_bytes, [in] uint64_t total_bytes); - /* Report that the nexe loaded successfully. */ - void ReportLoadSuccess([in] PP_Instance instance, - [in] uint64_t loaded_bytes, - [in] uint64_t total_bytes); - /* Report an error that occured while attempting to load a nexe. */ void ReportLoadError([in] PP_Instance instance, [in] PP_NaClError error, @@ -286,8 +279,6 @@ void ProcessNaClManifest([in] PP_Instance instance, [in] str_t program_url); - PP_Bool DevInterfacesEnabled([in] PP_Instance instance); - PP_Bool GetManifestProgramURL([in] PP_Instance instance, [out] PP_Var full_url, [out] PP_PNaClOptions pnacl_options, @@ -328,17 +319,6 @@ void LogTranslateTime([in] str_t histogram_name, [in] int64_t time_us); - /* Opens a manifest entry for the given instance. If this is for a helper - * process, we consult our internal pnacl.json instead of the user-supplied - * NMF. - * Fails for files which require PNaCl translation. - */ - void OpenManifestEntry([in] PP_Instance instance, - [in] PP_Bool is_helper_process, - [in] str_t key, - [out] PP_NaClFileInfo file_info, - [in] PP_CompletionCallback callback); - /* Sets the start time for PNaCl downloading and translation to the current * time. */
diff --git a/ppapi/c/private/ppb_nacl_private.h b/ppapi/c/private/ppb_nacl_private.h index d9fcd5fc..e80e35e 100644 --- a/ppapi/c/private/ppb_nacl_private.h +++ b/ppapi/c/private/ppb_nacl_private.h
@@ -3,7 +3,7 @@ * found in the LICENSE file. */ -/* From private/ppb_nacl_private.idl modified Thu Jan 22 07:26:18 2015. */ +/* From private/ppb_nacl_private.idl modified Fri Jan 23 09:09:44 2015. */ #ifndef PPAPI_C_PRIVATE_PPB_NACL_PRIVATE_H_ #define PPAPI_C_PRIVATE_PPB_NACL_PRIVATE_H_ @@ -211,8 +211,7 @@ struct PPB_NaCl_Private_1_0 { /* Launches NaCl's sel_ldr process. Returns PP_EXTERNAL_PLUGIN_OK on success * and writes a NaClHandle to imc_handle. Returns PP_EXTERNAL_PLUGIN_FAILED on - * failure. The |enable_ppapi_dev| parameter controls whether GetInterface - * returns 'Dev' interfaces to the NaCl plugin. + * failure. * The |nexe_file_info| is currently used only in non-SFI mode. It is the * file handle for the main nexe file, which should be initially loaded. * LaunchSelLdr takes the ownership of the file handle. @@ -224,7 +223,6 @@ const char* alleged_url, const struct PP_NaClFileInfo* nexe_file_info, PP_Bool uses_nonsfi_mode, - PP_Bool enable_ppapi_dev, PP_NaClAppProcessType process_type, void* imc_handle, struct PP_CompletionCallback callback); @@ -278,10 +276,6 @@ PP_Bool length_is_computable, uint64_t loaded_bytes, uint64_t total_bytes); - /* Report that the nexe loaded successfully. */ - void (*ReportLoadSuccess)(PP_Instance instance, - uint64_t loaded_bytes, - uint64_t total_bytes); /* Report an error that occured while attempting to load a nexe. */ void (*ReportLoadError)(PP_Instance instance, PP_NaClError error, @@ -310,7 +304,6 @@ * plugin. */ void (*ProcessNaClManifest)(PP_Instance instance, const char* program_url); - PP_Bool (*DevInterfacesEnabled)(PP_Instance instance); PP_Bool (*GetManifestProgramURL)(PP_Instance instance, struct PP_Var* full_url, struct PP_PNaClOptions* pnacl_options, @@ -344,16 +337,6 @@ * This function is safe to call on any thread. */ void (*LogTranslateTime)(const char* histogram_name, int64_t time_us); - /* Opens a manifest entry for the given instance. If this is for a helper - * process, we consult our internal pnacl.json instead of the user-supplied - * NMF. - * Fails for files which require PNaCl translation. - */ - void (*OpenManifestEntry)(PP_Instance instance, - PP_Bool is_helper_process, - const char* key, - struct PP_NaClFileInfo* file_info, - struct PP_CompletionCallback callback); /* Sets the start time for PNaCl downloading and translation to the current * time. */
diff --git a/ppapi/generators/OWNERS b/ppapi/generators/OWNERS index c3be9543..cdb12bc 100644 --- a/ppapi/generators/OWNERS +++ b/ppapi/generators/OWNERS
@@ -1,5 +1,8 @@ -yzshen@chromium.org +bradnelson@chromium.org +dmichael@chromium.org noelallen@chromium.org noelallen@google.com -sehr@google.com sehr@chromium.org +sehr@google.com +teravest@chromium.org +yzshen@chromium.org
diff --git a/ppapi/generators/idl_c_proto.py b/ppapi/generators/idl_c_proto.py index d6b9ebc..d5c99a7 100755 --- a/ppapi/generators/idl_c_proto.py +++ b/ppapi/generators/idl_c_proto.py
@@ -620,7 +620,7 @@ newest_dev = rel last_rel = build_list[-1] - # TODO(noelallen) : Bug 157017 finish multiversion support + # TODO(bradnelson) : Bug 157017 finish multiversion support if node.IsA('Struct'): if len(build_list) != 1: node.Error('Can not support multiple versions of node.')
diff --git a/ppapi/generators/idl_parser.py b/ppapi/generators/idl_parser.py index 51941d7..823dcf5a 100755 --- a/ppapi/generators/idl_parser.py +++ b/ppapi/generators/idl_parser.py
@@ -385,7 +385,7 @@ # Name=HEX | INT | OCT | FLOAT # Name="STRING" # Name=Function(arg ...) -# TODO(noelallen) -Not currently supported: +# TODO(bradnelson) -Not currently supported: # ** Name(arg ...) ... # ** Name=Scope::Value #
diff --git a/ppapi/nacl_irt/DEPS b/ppapi/nacl_irt/DEPS index 71177406..da4e94b 100644 --- a/ppapi/nacl_irt/DEPS +++ b/ppapi/nacl_irt/DEPS
@@ -7,7 +7,6 @@ # The untrusted build references the NaCl integrated runtime (IRT). "+native_client/src/public", - "+native_client/src/shared/srpc/nacl_srpc_ppapi_plugin_internal.h", "+native_client/src/untrusted/irt/irt.h", # The IRT also needs to know the errno and sysconf enums. "+native_client/src/trusted/service_runtime/include/sys/errno.h",
diff --git a/ppapi/nacl_irt/plugin_main.cc b/ppapi/nacl_irt/plugin_main.cc index 244bcbf..38ce9b6 100644 --- a/ppapi/nacl_irt/plugin_main.cc +++ b/ppapi/nacl_irt/plugin_main.cc
@@ -18,10 +18,6 @@ #include "ppapi/proxy/plugin_globals.h" #include "ppapi/shared_impl/ppb_audio_shared.h" -#if defined(__native_client__) -#include "native_client/src/shared/srpc/nacl_srpc_ppapi_plugin_internal.h" -#endif - void PpapiPluginRegisterThreadCreator( const struct PP_ThreadFunctions* thread_functions) { // Initialize all classes that need to create threads that call back into @@ -33,14 +29,6 @@ base::MessageLoop loop; ppapi::proxy::PluginGlobals plugin_globals; -#if defined(OS_NACL_SFI) - // This is currently needed so that the NaCl reverse service calls the - // StartupInitializationComplete() SRPC method, which unblocks plugin - // startup on the Chromium side. - // TODO(mseaborn): Remove the need to call this. - NaClPluginLowLevelInitializationComplete(); -#endif - ppapi::PpapiDispatcher ppapi_dispatcher( ppapi::GetIOThread()->message_loop_proxy(), ppapi::GetShutdownEvent(),
diff --git a/ppapi/native_client/DEPS b/ppapi/native_client/DEPS index 60de970..8ecee16 100644 --- a/ppapi/native_client/DEPS +++ b/ppapi/native_client/DEPS
@@ -3,6 +3,5 @@ "+native_client/src/public", "+native_client/src/shared/platform", "+native_client/src/shared/srpc", - "+native_client/src/trusted/weak_ref", "+native_client/src/untrusted", ]
diff --git a/ppapi/native_client/native_client.gyp b/ppapi/native_client/native_client.gyp index 91f081b..0735558d 100644 --- a/ppapi/native_client/native_client.gyp +++ b/ppapi/native_client/native_client.gyp
@@ -23,7 +23,6 @@ { 'destination': '>(tc_include_dir_newlib)/nacl', 'files': [ - 'src/trusted/weak_ref/call_on_main_thread.h', 'src/shared/ppapi_proxy/ppruntime.h', ], }, @@ -41,7 +40,6 @@ { 'destination': '>(tc_include_dir_glibc)/include/nacl', 'files': [ - 'src/trusted/weak_ref/call_on_main_thread.h', 'src/shared/ppapi_proxy/ppruntime.h', ], },
diff --git a/ppapi/native_client/src/trusted/plugin/DEPS b/ppapi/native_client/src/trusted/plugin/DEPS index 34d9609d..c45274ce1 100644 --- a/ppapi/native_client/src/trusted/plugin/DEPS +++ b/ppapi/native_client/src/trusted/plugin/DEPS
@@ -2,7 +2,6 @@ "+native_client/src/shared/imc/nacl_imc_c.h", "+native_client/src/trusted/desc", "+native_client/src/trusted/nonnacl_util/sel_ldr_launcher.h", - "+native_client/src/trusted/reverse_service/reverse_service.h", "+native_client/src/trusted/service_runtime/include", "+native_client/src/trusted/service_runtime/nacl_error_code.h", ]
diff --git a/ppapi/native_client/src/trusted/plugin/module_ppapi.h b/ppapi/native_client/src/trusted/plugin/module_ppapi.h index ee7bd19..9e520a1c 100644 --- a/ppapi/native_client/src/trusted/plugin/module_ppapi.h +++ b/ppapi/native_client/src/trusted/plugin/module_ppapi.h
@@ -13,11 +13,11 @@ public: ModulePpapi(); - virtual ~ModulePpapi(); + ~ModulePpapi() override; - virtual bool Init(); + bool Init() override; - virtual pp::Instance* CreateInstance(PP_Instance pp_instance); + pp::Instance* CreateInstance(PP_Instance pp_instance) override; private: bool init_was_successful_;
diff --git a/ppapi/native_client/src/trusted/plugin/nacl_subprocess.cc b/ppapi/native_client/src/trusted/plugin/nacl_subprocess.cc index c9d68d7a..891bcda 100644 --- a/ppapi/native_client/src/trusted/plugin/nacl_subprocess.cc +++ b/ppapi/native_client/src/trusted/plugin/nacl_subprocess.cc
@@ -6,12 +6,22 @@ #include <stdarg.h> +#include <sstream> + #include "native_client/src/shared/srpc/nacl_srpc.h" #include "ppapi/native_client/src/trusted/plugin/plugin_error.h" #include "ppapi/native_client/src/trusted/plugin/srpc_params.h" namespace plugin { +NaClSubprocess::NaClSubprocess(const std::string& description, + ServiceRuntime* service_runtime, + SrpcClient* srpc_client) + : description_(description), + service_runtime_(service_runtime), + srpc_client_(srpc_client) { +} + std::string NaClSubprocess::detailed_description() const { std::stringstream ss; ss << description()
diff --git a/ppapi/native_client/src/trusted/plugin/nacl_subprocess.h b/ppapi/native_client/src/trusted/plugin/nacl_subprocess.h index 0c231c61..37bb2fe 100644 --- a/ppapi/native_client/src/trusted/plugin/nacl_subprocess.h +++ b/ppapi/native_client/src/trusted/plugin/nacl_subprocess.h
@@ -31,11 +31,7 @@ public: NaClSubprocess(const std::string& description, ServiceRuntime* service_runtime, - SrpcClient* srpc_client) - : description_(description), - service_runtime_(service_runtime), - srpc_client_(srpc_client) { - } + SrpcClient* srpc_client); virtual ~NaClSubprocess(); ServiceRuntime* service_runtime() const { return service_runtime_.get(); }
diff --git a/ppapi/native_client/src/trusted/plugin/plugin.cc b/ppapi/native_client/src/trusted/plugin/plugin.cc index 4248c19..d4d373b 100644 --- a/ppapi/native_client/src/trusted/plugin/plugin.cc +++ b/ppapi/native_client/src/trusted/plugin/plugin.cc
@@ -65,8 +65,7 @@ new ServiceRuntime(this, pp_instance(), false, // No main_service_runtime. - false, // No non-SFI mode (i.e. in SFI-mode). - pp::BlockUntilComplete()); + false); // No non-SFI mode (i.e. in SFI-mode). // Now start the SelLdr instance. This must be created on the main thread. bool service_runtime_started = false; @@ -133,8 +132,7 @@ void Plugin::LoadNaClModule(PP_NaClFileInfo file_info, bool uses_nonsfi_mode, - PP_NaClAppProcessType process_type, - const pp::CompletionCallback& init_done_cb) { + PP_NaClAppProcessType process_type) { CHECK(pp::Module::Get()->core()->IsMainThread()); // Before forking a new sel_ldr process, ensure that we do not leak // the ServiceRuntime object for an existing subprocess, and that any @@ -150,7 +148,7 @@ process_type); ErrorInfo error_info; ServiceRuntime* service_runtime = new ServiceRuntime( - this, pp_instance(), true, uses_nonsfi_mode, init_done_cb); + this, pp_instance(), true, uses_nonsfi_mode); main_subprocess_.set_service_runtime(service_runtime); if (NULL == service_runtime) { error_info.SetReport( @@ -199,9 +197,8 @@ if (!LoadHelperNaClModuleInternal(nacl_subprocess.get(), params)) return NULL; - // We need not wait for the init_done callback. We can block - // here in StartSrpcServices, since helper NaCl modules - // are spawned from a private thread. + // We can block here in StartSrpcServices, since helper NaCl + // modules are spawned from a private thread. // // TODO(bsy): if helper module crashes, we should abort. // crash_cb is not used here, so we are relying on crashes @@ -309,9 +306,7 @@ LoadNaClModule( nexe_file_info_, uses_nonsfi_mode_, - PP_NATIVE_NACL_PROCESS_TYPE, - // No-op callback. - pp::CompletionCallback()); + PP_NATIVE_NACL_PROCESS_TYPE); } void Plugin::BitcodeDidTranslate(int32_t pp_error) { @@ -332,9 +327,7 @@ LoadNaClModule( info, false, /* uses_nonsfi_mode */ - PP_PNACL_PROCESS_TYPE, - // No-op callback. - pp::CompletionCallback()); + PP_PNACL_PROCESS_TYPE); } void Plugin::NaClManifestFileDidOpen(int32_t pp_error) {
diff --git a/ppapi/native_client/src/trusted/plugin/plugin.gyp b/ppapi/native_client/src/trusted/plugin/plugin.gyp index dc89f4e..2df9069 100644 --- a/ppapi/native_client/src/trusted/plugin/plugin.gyp +++ b/ppapi/native_client/src/trusted/plugin/plugin.gyp
@@ -24,8 +24,6 @@ '<(DEPTH)/native_client/src/trusted/nonnacl_util/nonnacl_util.gyp:sel_ldr_launcher_base', '<(DEPTH)/native_client/src/trusted/platform_qualify/platform_qualify.gyp:platform_qual_lib', '<(DEPTH)/native_client/src/trusted/simple_service/simple_service.gyp:simple_service', - '<(DEPTH)/native_client/src/trusted/reverse_service/reverse_service.gyp:reverse_service', - '<(DEPTH)/native_client/src/trusted/weak_ref/weak_ref.gyp:weak_ref', '<(DEPTH)/ppapi/ppapi.gyp:ppapi_cpp_objects', '<(DEPTH)/ppapi/ppapi.gyp:ppapi_internal_module', ],
diff --git a/ppapi/native_client/src/trusted/plugin/plugin.h b/ppapi/native_client/src/trusted/plugin/plugin.h index ca619f9..b1855f9 100644 --- a/ppapi/native_client/src/trusted/plugin/plugin.h +++ b/ppapi/native_client/src/trusted/plugin/plugin.h
@@ -63,10 +63,10 @@ // Initializes this plugin with <embed/object ...> tag attribute count |argc|, // names |argn| and values |argn|. Returns false on failure. // Gets called by the browser right after New(). - virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]); + bool Init(uint32_t argc, const char* argn[], const char* argv[]) override; // Handles document load, when the plugin is a MIME type handler. - virtual bool HandleDocumentLoad(const pp::URLLoader& url_loader); + bool HandleDocumentLoad(const pp::URLLoader& url_loader) override; // Load support. // @@ -85,16 +85,7 @@ // mechanism(s) take over. void LoadNaClModule(PP_NaClFileInfo file_info, bool uses_nonsfi_mode, - PP_NaClAppProcessType process_type, - const pp::CompletionCallback& init_done_cb); - - // Continuation for starting SRPC/JSProxy services as appropriate. - // This is invoked as a callback when the NaCl module makes the - // init_done reverse RPC to tell us that low-level initialization - // such as ld.so processing is done. That initialization requires - // that the main thread be free in order to do Pepper - // main-thread-only operations such as file processing. - bool LoadNaClModuleContinuation(int32_t pp_error); + PP_NaClAppProcessType process_type); // Load support. // A helper SRPC NaCl module can be loaded given a PP_NaClFileInfo. @@ -117,7 +108,7 @@ NACL_DISALLOW_COPY_AND_ASSIGN(Plugin); // The browser will invoke the destructor via the pp::Instance // pointer to this object, not from base's Delete(). - ~Plugin(); + ~Plugin() override; // Shuts down socket connection, service runtime, and receive thread, // in this order, for the main nacl subprocess.
diff --git a/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc b/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc index 6c81745..74451845 100644 --- a/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc +++ b/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc
@@ -5,6 +5,7 @@ #include "ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h" #include <algorithm> +#include <sstream> #include <utility> #include "native_client/src/include/portability_io.h"
diff --git a/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.cc b/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.cc index 8acabeb..12f776c 100644 --- a/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.cc +++ b/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.cc
@@ -5,7 +5,9 @@ #include "ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.h" #include <iterator> +#include <sstream> +#include "native_client/src/shared/platform/nacl_check.h" #include "native_client/src/trusted/desc/nacl_desc_wrapper.h" #include "ppapi/cpp/var.h" #include "ppapi/native_client/src/trusted/plugin/plugin.h"
diff --git a/ppapi/native_client/src/trusted/plugin/sel_ldr_launcher_chrome.h b/ppapi/native_client/src/trusted/plugin/sel_ldr_launcher_chrome.h index c8857d84..41b2463 100644 --- a/ppapi/native_client/src/trusted/plugin/sel_ldr_launcher_chrome.h +++ b/ppapi/native_client/src/trusted/plugin/sel_ldr_launcher_chrome.h
@@ -14,7 +14,7 @@ class SelLdrLauncherChrome : public nacl::SelLdrLauncherBase { public: - virtual bool Start(const char* url); + bool Start(const char* url) override; // Provides a way for LaunchSelLdr() to write bootstrap channel information // into this class.
diff --git a/ppapi/native_client/src/trusted/plugin/service_runtime.cc b/ppapi/native_client/src/trusted/plugin/service_runtime.cc index dfbf8258..e58efd04 100644 --- a/ppapi/native_client/src/trusted/plugin/service_runtime.cc +++ b/ppapi/native_client/src/trusted/plugin/service_runtime.cc
@@ -39,215 +39,17 @@ #include "ppapi/native_client/src/trusted/plugin/sel_ldr_launcher_chrome.h" #include "ppapi/native_client/src/trusted/plugin/srpc_client.h" #include "ppapi/native_client/src/trusted/plugin/utility.h" -#include "ppapi/native_client/src/trusted/weak_ref/call_on_main_thread.h" namespace plugin { -OpenManifestEntryResource::~OpenManifestEntryResource() { -} - -PluginReverseInterface::PluginReverseInterface( - nacl::WeakRefAnchor* anchor, - PP_Instance pp_instance, - ServiceRuntime* service_runtime, - pp::CompletionCallback init_done_cb) - : anchor_(anchor), - pp_instance_(pp_instance), - service_runtime_(service_runtime), - shutting_down_(false), - init_done_cb_(init_done_cb) { - NaClXMutexCtor(&mu_); - NaClXCondVarCtor(&cv_); -} - -PluginReverseInterface::~PluginReverseInterface() { - NaClCondVarDtor(&cv_); - NaClMutexDtor(&mu_); -} - -void PluginReverseInterface::ShutDown() { - NaClLog(4, "PluginReverseInterface::Shutdown: entered\n"); - nacl::MutexLocker take(&mu_); - shutting_down_ = true; - NaClXCondVarBroadcast(&cv_); - NaClLog(4, "PluginReverseInterface::Shutdown: broadcasted, exiting\n"); -} - -void PluginReverseInterface::DoPostMessage(std::string message) { - // This feature is no longer used. - // TODO(teravest): Remove this once this is gone from nacl::ReverseInterface. -} - -void PluginReverseInterface::StartupInitializationComplete() { - NaClLog(4, "PluginReverseInterface::StartupInitializationComplete\n"); - if (init_done_cb_.pp_completion_callback().func != NULL) { - NaClLog(4, - "PluginReverseInterface::StartupInitializationComplete:" - " invoking CB\n"); - pp::Module::Get()->core()->CallOnMainThread(0, init_done_cb_, PP_OK); - } else { - NaClLog(1, - "PluginReverseInterface::StartupInitializationComplete:" - " init_done_cb_ not valid, skipping.\n"); - } -} - -// TODO(bsy): OpenManifestEntry should use the manifest to ResolveKey -// and invoke StreamAsFile with a completion callback that invokes -// GetPOSIXFileDesc. -bool PluginReverseInterface::OpenManifestEntry(std::string url_key, - struct NaClFileInfo* info) { - // This method should only ever be called from the PNaCl translator, as the - // IRT is not available there. - // TODO(teravest): Remove support for OpenManifestEntry here once - // crbug.com/302078 is resolved. - if (service_runtime_->main_service_runtime()) { - NaClLog(LOG_ERROR, - "OpenManifestEntry should only be used by PNaCl translator.\n"); - return false; - } - - bool op_complete = false; // NB: mu_ and cv_ also controls access to this! - // The to_open object is owned by the weak ref callback. Because this function - // waits for the callback to finish, the to_open object will be deallocated on - // the main thread before this function can return. The pointers it contains - // to stack variables will not leak. - OpenManifestEntryResource* to_open = - new OpenManifestEntryResource(url_key, info, &op_complete); - CHECK(to_open != NULL); - NaClLog(4, "PluginReverseInterface::OpenManifestEntry: %s\n", - url_key.c_str()); - // This assumes we are not on the main thread. If false, we deadlock. - plugin::WeakRefCallOnMainThread( - anchor_, - 0, - this, - &plugin::PluginReverseInterface::OpenManifestEntry_MainThreadContinuation, - to_open); - NaClLog(4, - "PluginReverseInterface::OpenManifestEntry:" - " waiting on main thread\n"); - - { - nacl::MutexLocker take(&mu_); - while (!shutting_down_ && !op_complete) - NaClXCondVarWait(&cv_, &mu_); - NaClLog(4, "PluginReverseInterface::OpenManifestEntry: done!\n"); - if (shutting_down_) { - NaClLog(4, - "PluginReverseInterface::OpenManifestEntry:" - " plugin is shutting down\n"); - return false; - } - } - - // info->desc has the returned descriptor if successful, else -1. - - // The caller is responsible for not closing info->desc. If it is - // closed prematurely, then another open could re-use the OS - // descriptor, confusing the opened_ map. If the caller is going to - // want to make a NaClDesc object and transfer it etc., then the - // caller should DUP the descriptor (but remember the original - // value) for use by the NaClDesc object, which closes when the - // object is destroyed. - NaClLog(4, - "PluginReverseInterface::OpenManifestEntry: info->desc = %d\n", - info->desc); - if (info->desc == -1) { - // TODO(bsy,ncbray): what else should we do with the error? This - // is a runtime error that may simply be a programming error in - // the untrusted code, or it may be something else wrong w/ the - // manifest. - NaClLog(4, "OpenManifestEntry: failed for key %s", url_key.c_str()); - } - return true; -} - -// Transfer point from OpenManifestEntry() which runs on the main thread -// (Some PPAPI actions -- like StreamAsFile -- can only run on the main thread). -// OpenManifestEntry() is waiting on a condvar for this continuation to -// complete. We Broadcast and awaken OpenManifestEntry() whenever we are done -// either here, or in a later MainThreadContinuation step, if there are -// multiple steps. -void PluginReverseInterface::OpenManifestEntry_MainThreadContinuation( - OpenManifestEntryResource* p, - int32_t err) { - UNREFERENCED_PARAMETER(err); - // CallOnMainThread continuations always called with err == PP_OK. - - NaClLog(4, "Entered OpenManifestEntry_MainThreadContinuation\n"); - - // Because p is owned by the callback of this invocation, so it is necessary - // to create another instance. - OpenManifestEntryResource* open_cont = new OpenManifestEntryResource(*p); - pp::CompletionCallback stream_cc = WeakRefNewCallback( - anchor_, - this, - &PluginReverseInterface::StreamAsFile_MainThreadContinuation, - open_cont); - - GetNaClInterface()->OpenManifestEntry( - pp_instance_, - PP_FromBool(!service_runtime_->main_service_runtime()), - p->url.c_str(), - &open_cont->pp_file_info, - stream_cc.pp_completion_callback()); - // p is deleted automatically. -} - -void PluginReverseInterface::StreamAsFile_MainThreadContinuation( - OpenManifestEntryResource* p, - int32_t result) { - NaClLog(4, "Entered StreamAsFile_MainThreadContinuation\n"); - { - nacl::MutexLocker take(&mu_); - if (result == PP_OK) { - // We downloaded this file to temporary storage for this plugin; it's - // reasonable to provide a file descriptor with write access. - p->file_info->desc = ConvertFileDescriptor(p->pp_file_info.handle, false); - p->file_info->file_token.lo = p->pp_file_info.token_lo; - p->file_info->file_token.hi = p->pp_file_info.token_hi; - NaClLog(4, - "StreamAsFile_MainThreadContinuation: PP_OK, desc %d\n", - p->file_info->desc); - } else { - NaClLog( - 4, - "StreamAsFile_MainThreadContinuation: !PP_OK, setting desc -1\n"); - p->file_info->desc = -1; - } - *p->op_complete_ptr = true; - NaClXCondVarBroadcast(&cv_); - } -} - -void PluginReverseInterface::ReportCrash() { - // This is now handled through Chromium IPC. -} - -void PluginReverseInterface::ReportExitStatus(int exit_status) { - // We do nothing here; reporting exit status is handled through a separate - // embedder interface. -} - -int64_t PluginReverseInterface::RequestQuotaForWrite( - std::string file_id, int64_t offset, int64_t bytes_to_write) { - return bytes_to_write; -} - ServiceRuntime::ServiceRuntime(Plugin* plugin, PP_Instance pp_instance, bool main_service_runtime, - bool uses_nonsfi_mode, - pp::CompletionCallback init_done_cb) + bool uses_nonsfi_mode) : plugin_(plugin), pp_instance_(pp_instance), main_service_runtime_(main_service_runtime), uses_nonsfi_mode_(uses_nonsfi_mode), - reverse_service_(NULL), - anchor_(new nacl::WeakRefAnchor()), - rev_interface_(new PluginReverseInterface(anchor_, pp_instance, this, - init_done_cb)), start_sel_ldr_done_(false), sel_ldr_wait_timed_out_(false), start_nexe_done_(false), @@ -281,53 +83,6 @@ return true; } -bool ServiceRuntime::InitReverseService() { - if (uses_nonsfi_mode_) { - // In non-SFI mode, no reverse service is set up. Just returns success. - return true; - } - - // Hook up the reverse service channel. We are the IMC client, but - // provide SRPC service. - NaClDesc* out_conn_cap; - NaClSrpcResultCodes rpc_result = - NaClSrpcInvokeBySignature(&command_channel_, - "reverse_setup::h", - &out_conn_cap); - - if (NACL_SRPC_RESULT_OK != rpc_result) { - ErrorInfo error_info; - error_info.SetReport(PP_NACL_ERROR_SEL_LDR_COMMUNICATION_REV_SETUP, - "ServiceRuntime: reverse setup rpc failed"); - ReportLoadError(error_info); - return false; - } - // Get connection capability to service runtime where the IMC - // server/SRPC client is waiting for a rendezvous. - NaClLog(4, "ServiceRuntime: got 0x%" NACL_PRIxPTR "\n", - (uintptr_t) out_conn_cap); - nacl::DescWrapper* conn_cap = plugin_->wrapper_factory()->MakeGenericCleanup( - out_conn_cap); - if (conn_cap == NULL) { - ErrorInfo error_info; - error_info.SetReport(PP_NACL_ERROR_SEL_LDR_COMMUNICATION_WRAPPER, - "ServiceRuntime: wrapper allocation failure"); - ReportLoadError(error_info); - return false; - } - out_conn_cap = NULL; // ownership passed - NaClLog(4, "ServiceRuntime::InitReverseService: starting reverse service\n"); - reverse_service_ = new nacl::ReverseService(conn_cap, rev_interface_->Ref()); - if (!reverse_service_->Start()) { - ErrorInfo error_info; - error_info.SetReport(PP_NACL_ERROR_SEL_LDR_COMMUNICATION_REV_SERVICE, - "ServiceRuntime: starting reverse services failed"); - ReportLoadError(error_info); - return false; - } - return true; -} - bool ServiceRuntime::StartModule() { // start the module. otherwise we cannot connect for multimedia // subsystem since that is handled by user-level code (not secure!) @@ -389,16 +144,12 @@ return; } - bool enable_dev_interfaces = - GetNaClInterface()->DevInterfacesEnabled(pp_instance_); - GetNaClInterface()->LaunchSelLdr( pp_instance_, PP_FromBool(main_service_runtime_), params.url.c_str(), ¶ms.file_info, PP_FromBool(uses_nonsfi_mode_), - PP_FromBool(enable_dev_interfaces), params.process_type, &bootstrap_channel_, callback.pp_completion_callback()); @@ -473,8 +224,6 @@ bool ServiceRuntime::StartNexeInternal() { if (!SetupCommandChannel()) return false; - if (!InitReverseService()) - return false; return StartModule(); } @@ -530,8 +279,6 @@ } void ServiceRuntime::Shutdown() { - rev_interface_->ShutDown(); - anchor_->Abandon(); // Abandon callbacks, tell service threads to quit if they were // blocked waiting for main thread operations to finish. Note that // some callbacks must still await their completion event, e.g., @@ -543,17 +290,6 @@ subprocess_.reset(NULL); NaClSrpcDtor(&command_channel_); - - // subprocess_ has been shut down, but threads waiting on messages - // from the service runtime may not have noticed yet. The low-level - // NaClSimpleRevService code takes care to refcount the data objects - // that it needs, and reverse_service_ is also refcounted. We wait - // for the service threads to get their EOF indications. - if (reverse_service_ != NULL) { - reverse_service_->WaitForServiceThreadsToExit(); - reverse_service_->Unref(); - reverse_service_ = NULL; - } } ServiceRuntime::~ServiceRuntime() { @@ -561,12 +297,7 @@ static_cast<void*>(this)); // We do this just in case Shutdown() was not called. subprocess_.reset(NULL); - if (reverse_service_ != NULL) - reverse_service_->Unref(); - rev_interface_->Unref(); - - anchor_->Unref(); NaClCondVarDtor(&cond_); NaClMutexDtor(&mu_); }
diff --git a/ppapi/native_client/src/trusted/plugin/service_runtime.h b/ppapi/native_client/src/trusted/plugin/service_runtime.h index b720bd24..2fa78b4 100644 --- a/ppapi/native_client/src/trusted/plugin/service_runtime.h +++ b/ppapi/native_client/src/trusted/plugin/service_runtime.h
@@ -13,10 +13,9 @@ #include "native_client/src/include/nacl_macros.h" #include "native_client/src/include/nacl_scoped_ptr.h" +#include "native_client/src/public/imc_types.h" #include "native_client/src/shared/platform/nacl_sync.h" #include "native_client/src/shared/srpc/nacl_srpc.h" -#include "native_client/src/trusted/reverse_service/reverse_service.h" -#include "native_client/src/trusted/weak_ref/weak_ref.h" #include "ppapi/cpp/completion_callback.h" #include "ppapi/native_client/src/trusted/plugin/utility.h" @@ -46,86 +45,13 @@ PP_NaClAppProcessType process_type; }; -// Callback resources are essentially our continuation state. -struct OpenManifestEntryResource { - public: - OpenManifestEntryResource(const std::string& target_url, - struct NaClFileInfo* finfo, - bool* op_complete) - : url(target_url), - file_info(finfo), - op_complete_ptr(op_complete) {} - ~OpenManifestEntryResource(); - - std::string url; - struct NaClFileInfo* file_info; - PP_NaClFileInfo pp_file_info; - bool* op_complete_ptr; -}; - -// Do not invoke from the main thread, since the main methods will -// invoke CallOnMainThread and then wait on a condvar for the task to -// complete: if invoked from the main thread, the main method not -// returning (and thus unblocking the main thread) means that the -// main-thread continuation methods will never get called, and thus -// we'd get a deadlock. -class PluginReverseInterface: public nacl::ReverseInterface { - public: - PluginReverseInterface(nacl::WeakRefAnchor* anchor, - PP_Instance pp_instance, - ServiceRuntime* service_runtime, - pp::CompletionCallback init_done_cb); - - virtual ~PluginReverseInterface(); - - void ShutDown(); - - virtual void DoPostMessage(std::string message); - - virtual void StartupInitializationComplete(); - - virtual bool OpenManifestEntry(std::string url_key, - struct NaClFileInfo *info); - - virtual void ReportCrash(); - - virtual void ReportExitStatus(int exit_status); - - // TODO(teravest): Remove this method once it's gone from - // nacl::ReverseInterface. - virtual int64_t RequestQuotaForWrite(std::string file_id, - int64_t offset, - int64_t bytes_to_write); - - protected: - virtual void OpenManifestEntry_MainThreadContinuation( - OpenManifestEntryResource* p, - int32_t err); - - virtual void StreamAsFile_MainThreadContinuation( - OpenManifestEntryResource* p, - int32_t result); - - private: - nacl::WeakRefAnchor* anchor_; // holds a ref - // Should be used only in main thread in WeakRef-protected callbacks. - PP_Instance pp_instance_; - ServiceRuntime* service_runtime_; - NaClMutex mu_; - NaClCondVar cv_; - bool shutting_down_; - - pp::CompletionCallback init_done_cb_; -}; - // ServiceRuntime abstracts a NativeClient sel_ldr instance. class ServiceRuntime { public: ServiceRuntime(Plugin* plugin, PP_Instance pp_instance, bool main_service_runtime, - bool uses_nonsfi_mode, - pp::CompletionCallback init_done_cb); + bool uses_nonsfi_mode); // The destructor terminates the sel_ldr process. ~ServiceRuntime(); @@ -173,7 +99,6 @@ bool StartNexeInternal(); bool SetupCommandChannel(); - bool InitReverseService(); bool StartModule(); void ReapLogs(); @@ -184,13 +109,8 @@ PP_Instance pp_instance_; bool main_service_runtime_; bool uses_nonsfi_mode_; - nacl::ReverseService* reverse_service_; nacl::scoped_ptr<SelLdrLauncherChrome> subprocess_; - nacl::WeakRefAnchor* anchor_; - - PluginReverseInterface* rev_interface_; - // Mutex and CondVar to protect start_sel_ldr_done_ and nexe_started_. NaClMutex mu_; NaClCondVar cond_;
diff --git a/ppapi/native_client/src/trusted/weak_ref/call_on_main_thread.h b/ppapi/native_client/src/trusted/weak_ref/call_on_main_thread.h deleted file mode 100644 index a618795..0000000 --- a/ppapi/native_client/src/trusted/weak_ref/call_on_main_thread.h +++ /dev/null
@@ -1,252 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright (c) 2011 The Chromium Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -// EXAMPLE USAGE -// -// class PluginReverseInterface { -// public: -// PluginReverseInterface(...) : anchor_(new nacl::WeakRefAnchor); -// ~PluginReverseInterface() { anchor_->Abandon(); } -// void Log(nacl::string message) { -// LogContinuation* continuation = new LogContinuation(message); -// plugin::WeakRefCallOnMainThread(anchor_, 0 /* ms delay */, -// this, &PluginReverseInterface::Log_cont, -// continuation); -// } -// void Log_cont(LogContinuation* cont, int32_t result) { -// plugin_->browser_interface()->AddToConsole(plugin_->instance_id(), -// cont->message); -// delete cont; -// } -// private: -// nacl::WeakRefAnchor* anchor_; -// } - -#ifndef NATIVE_CLIENT_SRC_TRUSTED_WEAK_REF_CALL_ON_MAIN_THREAD_H_ -#define NATIVE_CLIENT_SRC_TRUSTED_WEAK_REF_CALL_ON_MAIN_THREAD_H_ - -#include "native_client/src/trusted/weak_ref/weak_ref.h" - -#include "native_client/src/include/nacl_scoped_ptr.h" -#include "native_client/src/include/nacl_compiler_annotations.h" -#include "native_client/src/include/portability.h" - -#include "ppapi/c/pp_errors.h" // for PP_OK -#include "ppapi/cpp/completion_callback.h" // for pp::CompletionCallback -#include "ppapi/cpp/core.h" // for pp:: -#include "ppapi/cpp/module.h" // for pp::Module - -namespace plugin { - -// A typesafe utility to schedule a completion callback using weak -// references. The callback function callback_fn is invoked -// regardless of whether the anchor has been abandoned, since -// callback_fn takes a WeakRef<R>* as argument. The intention is that -// such callbacks, even deprived of any of its arguments (which has -// been deleted), may wish to do some cleanup / log a message. - -static char const* const kPpWeakRefModuleName = "pp_weak_ref"; - -template <typename R> pp::CompletionCallback WeakRefNewCallback( - nacl::WeakRefAnchor* anchor, - void callback_fn(nacl::WeakRef<R>* weak_data, int32_t err), - R* raw_data) { - nacl::WeakRef<R>* wp = anchor->MakeWeakRef<R>(raw_data); - // TODO(bsy): explore using another template to eliminate the - // following cast, making things completely typesafe. - pp::CompletionCallback cc_nrvo( - reinterpret_cast<void (*)(void*, int32_t)>( - callback_fn), - reinterpret_cast<void*>(wp)); - return cc_nrvo; -} - -template <typename R> void WeakRefCallOnMainThread( - nacl::WeakRefAnchor* anchor, - int32_t delay_in_milliseconds, - void callback_fn(nacl::WeakRef<R>* weak_data, int32_t err), - R* raw_data) { - pp::CompletionCallback cc = - WeakRefNewCallback(anchor, callback_fn, raw_data, &cc); - - pp::Module::Get()->core()->CallOnMainThread( - delay_in_milliseconds, - cc, - PP_OK); -} - -template <typename R> class WeakRefAutoAbandonWrapper { - public: - WeakRefAutoAbandonWrapper(void (*callback_fn)(R* raw_data, - int32_t err), - R* raw_data) - : orig_callback_fn(callback_fn), - orig_data(raw_data) {} - - void (*orig_callback_fn)(R* raw_data, int32_t err); - nacl::scoped_ptr<R> orig_data; -}; - -/* - * It would be nice if the function had the right type signature, - * i.e., void WeakRefAutoAbandoner(void *wr_data, int32_t) but then - * the formal argument list would not use the typename template - * argument R, making template resolution impossible. - */ -template <typename R> void WeakRefAutoAbandoner( - nacl::WeakRef<WeakRefAutoAbandonWrapper<R> >* wr, - int32_t err) { - nacl::scoped_ptr<WeakRefAutoAbandonWrapper<R> > p; - wr->ReleaseAndUnref(&p); - if (p == NULL) { - NaClLog2(kPpWeakRefModuleName, 4, - "WeakRefAutoAbandoner: weak ref NULL, anchor was abandoned\n"); - return; - } - NaClLog2(kPpWeakRefModuleName, 4, - "WeakRefAutoAbandoner: weak ref okay, invoking callback\n"); - (*p->orig_callback_fn)(p->orig_data.get(), err); - return; -} - -// A typesafe utility to schedule a completion callback using weak -// references. The callback function raw_callback_fn takes an R* as -// argument, and is not invoked if the anchor has been abandoned. -template <typename R> pp::CompletionCallback WeakRefNewCallback( - nacl::WeakRefAnchor* anchor, - void (*raw_callback_fn)(R* raw_data, int32_t err), - R* raw_data) { - - WeakRefAutoAbandonWrapper<R>* wref_auto_wrapper = - new WeakRefAutoAbandonWrapper<R>(raw_callback_fn, raw_data); - - CHECK(wref_auto_wrapper != NULL); - - nacl::WeakRef<WeakRefAutoAbandonWrapper<R> >* wp = - anchor->MakeWeakRef<WeakRefAutoAbandonWrapper<R> >( - wref_auto_wrapper); - void (*weak_ref_auto_abandoner_ptr)( - nacl::WeakRef<WeakRefAutoAbandonWrapper<R> >* wr, - int32_t err) = WeakRefAutoAbandoner<R>; - // TODO(bsy): see above - pp::CompletionCallback cc_nrvo( - reinterpret_cast<void (*)(void*, int32_t)>(weak_ref_auto_abandoner_ptr), - reinterpret_cast<void*>(wp)); - return cc_nrvo; -} - -template <typename R> void WeakRefCallOnMainThread( - nacl::WeakRefAnchor* anchor, - int32_t delay_in_milliseconds, - void raw_callback_fn(R* raw_data, int32_t err), - R* raw_data) { - pp::CompletionCallback cc = - WeakRefNewCallback(anchor, raw_callback_fn, raw_data, &cc); - pp::Module::Get()->core()->CallOnMainThread( - delay_in_milliseconds, - cc, - PP_OK); -} - - -template <typename R, typename E> -class WeakRefMemberFuncBinder { - public: - WeakRefMemberFuncBinder(E* object, - void (E::*raw_callback_fn)(R* raw_data, - int32_t err), - R* raw_data) - : object_(object), - raw_callback_fn_(raw_callback_fn), - data_(raw_data) {} - void Invoke(int32_t err) { - NaClLog2(kPpWeakRefModuleName, 4, - ("WeakRefMemberFuncBinder: Invoke obj 0x%" NACL_PRIxPTR - ", err%" NACL_PRId32 "\n"), - reinterpret_cast<uintptr_t>(object_), err); - (object_->*raw_callback_fn_)(data_.get(), err); - NaClLog2(kPpWeakRefModuleName, 4, - "WeakRefMemberFuncBinder: done\n"); - } - private: - E* object_; - void (E::*raw_callback_fn_)(R* raw_data, int32_t err); - nacl::scoped_ptr<R> data_; -}; - -template <typename R, typename E> -void WeakRefMemberFuncInvoker( - WeakRefMemberFuncBinder<R, E> *binder, int32_t err) { - NaClLog2(kPpWeakRefModuleName, 4, - "WeakRefMemberFuncInvoker: %" NACL_PRIxPTR " %" NACL_PRId32 "\n", - (uintptr_t) binder, - err); - binder->Invoke(err); - // delete binder not needed, since WeakRefAutoAbandoner holds binder - // in a scoped_ptr and will automatically delete on scope exit. -} - - -// A typesafe utility to schedule a completion callback using weak -// references, where the callback function is a member function. The -// member function must take only a raw argument data pointer and a -// completion status as formal parameters. The lifetime of the -// |object| and |raw_callback_fn| must be at least that of |anchor|. -// Typically |object| is just the object that controls the |anchor|, -// though it may be some sub-object that is contained within the -// actual controlling object. If the |anchor| is abandoned, the -// |raw_data| argument is deleted and the |raw_callback_fn| will not -// be invoked. -template <typename R, typename E> -pp::CompletionCallback WeakRefNewCallback( - nacl::WeakRefAnchor* anchor, - E* object, - void (E::*raw_callback_fn)(R* raw_data, int32_t err), - R* raw_data) { - NaClLog2(kPpWeakRefModuleName, 4, - "Entered WeakRefNewCallback\n"); - NaClLog2(kPpWeakRefModuleName, 4, - "object 0x%" NACL_PRIxPTR "\n", - reinterpret_cast<uintptr_t>(object)); - WeakRefMemberFuncBinder<R, E>* binder = - new WeakRefMemberFuncBinder<R, E>(object, - raw_callback_fn, - raw_data); - CHECK(binder != NULL); - NaClLog2(kPpWeakRefModuleName, 4, - "WeakRefNewCallback: binder %" NACL_PRIxPTR "\n", - (uintptr_t) binder); - void (*weak_ref_member_func_invoker_ptr)( - WeakRefMemberFuncBinder<R, E>* binder, - int32_t err) = WeakRefMemberFuncInvoker<R, E>; - return WeakRefNewCallback(anchor, weak_ref_member_func_invoker_ptr, - binder); -} - -template <typename R, typename E> void WeakRefCallOnMainThread( - nacl::WeakRefAnchor* anchor, - int32_t delay_in_milliseconds, - E* object, - void (E::*raw_callback_fn)(R* raw_data, int32_t err), - R* raw_data) { - NaClLog2(kPpWeakRefModuleName, 4, - "Entered WeakRefCallOnMainThread\n"); - pp::CompletionCallback cc = - WeakRefNewCallback(anchor, object, raw_callback_fn, raw_data); - NaClLog2(kPpWeakRefModuleName, 4, - "WeakRefCallOnMainThread: got cc\n"); - pp::Module::Get()->core()->CallOnMainThread( - delay_in_milliseconds, - cc, - PP_OK); - NaClLog2(kPpWeakRefModuleName, 4, - "WeakRefCallOnMainThread: invoked PP_CallOnMainThread\n"); -} - -} // namespace plugin - -#endif
diff --git a/ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c b/ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c index c4cde223..6d42f33 100644 --- a/ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c +++ b/ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c
@@ -3600,9 +3600,9 @@ /* Begin wrapper methods for PPB_NaCl_Private_1_0 */ -static void Pnacl_M25_PPB_NaCl_Private_LaunchSelLdr(PP_Instance instance, PP_Bool main_service_runtime, const char* alleged_url, const struct PP_NaClFileInfo* nexe_file_info, PP_Bool uses_nonsfi_mode, PP_Bool enable_ppapi_dev, PP_NaClAppProcessType process_type, void* imc_handle, struct PP_CompletionCallback* callback) { +static void Pnacl_M25_PPB_NaCl_Private_LaunchSelLdr(PP_Instance instance, PP_Bool main_service_runtime, const char* alleged_url, const struct PP_NaClFileInfo* nexe_file_info, PP_Bool uses_nonsfi_mode, PP_NaClAppProcessType process_type, void* imc_handle, struct PP_CompletionCallback* callback) { const struct PPB_NaCl_Private_1_0 *iface = Pnacl_WrapperInfo_PPB_NaCl_Private_1_0.real_iface; - iface->LaunchSelLdr(instance, main_service_runtime, alleged_url, nexe_file_info, uses_nonsfi_mode, enable_ppapi_dev, process_type, imc_handle, *callback); + iface->LaunchSelLdr(instance, main_service_runtime, alleged_url, nexe_file_info, uses_nonsfi_mode, process_type, imc_handle, *callback); } static int32_t Pnacl_M25_PPB_NaCl_Private_UrandomFD(void) { @@ -3640,11 +3640,6 @@ iface->DispatchEvent(instance, event_type, resource_url, length_is_computable, loaded_bytes, total_bytes); } -static void Pnacl_M25_PPB_NaCl_Private_ReportLoadSuccess(PP_Instance instance, uint64_t loaded_bytes, uint64_t total_bytes) { - const struct PPB_NaCl_Private_1_0 *iface = Pnacl_WrapperInfo_PPB_NaCl_Private_1_0.real_iface; - iface->ReportLoadSuccess(instance, loaded_bytes, total_bytes); -} - static void Pnacl_M25_PPB_NaCl_Private_ReportLoadError(PP_Instance instance, PP_NaClError error, const char* error_message) { const struct PPB_NaCl_Private_1_0 *iface = Pnacl_WrapperInfo_PPB_NaCl_Private_1_0.real_iface; iface->ReportLoadError(instance, error, error_message); @@ -3690,11 +3685,6 @@ iface->ProcessNaClManifest(instance, program_url); } -static PP_Bool Pnacl_M25_PPB_NaCl_Private_DevInterfacesEnabled(PP_Instance instance) { - const struct PPB_NaCl_Private_1_0 *iface = Pnacl_WrapperInfo_PPB_NaCl_Private_1_0.real_iface; - return iface->DevInterfacesEnabled(instance); -} - static PP_Bool Pnacl_M25_PPB_NaCl_Private_GetManifestProgramURL(PP_Instance instance, struct PP_Var* full_url, struct PP_PNaClOptions* pnacl_options, PP_Bool* uses_nonsfi_mode) { const struct PPB_NaCl_Private_1_0 *iface = Pnacl_WrapperInfo_PPB_NaCl_Private_1_0.real_iface; return iface->GetManifestProgramURL(instance, full_url, pnacl_options, uses_nonsfi_mode); @@ -3725,11 +3715,6 @@ iface->LogTranslateTime(histogram_name, time_us); } -static void Pnacl_M25_PPB_NaCl_Private_OpenManifestEntry(PP_Instance instance, PP_Bool is_helper_process, const char* key, struct PP_NaClFileInfo* file_info, struct PP_CompletionCallback* callback) { - const struct PPB_NaCl_Private_1_0 *iface = Pnacl_WrapperInfo_PPB_NaCl_Private_1_0.real_iface; - iface->OpenManifestEntry(instance, is_helper_process, key, file_info, *callback); -} - static void Pnacl_M25_PPB_NaCl_Private_SetPNaClStartTime(PP_Instance instance) { const struct PPB_NaCl_Private_1_0 *iface = Pnacl_WrapperInfo_PPB_NaCl_Private_1_0.real_iface; iface->SetPNaClStartTime(instance); @@ -5597,7 +5582,7 @@ }; static const struct PPB_NaCl_Private_1_0 Pnacl_Wrappers_PPB_NaCl_Private_1_0 = { - .LaunchSelLdr = (void (*)(PP_Instance instance, PP_Bool main_service_runtime, const char* alleged_url, const struct PP_NaClFileInfo* nexe_file_info, PP_Bool uses_nonsfi_mode, PP_Bool enable_ppapi_dev, PP_NaClAppProcessType process_type, void* imc_handle, struct PP_CompletionCallback callback))&Pnacl_M25_PPB_NaCl_Private_LaunchSelLdr, + .LaunchSelLdr = (void (*)(PP_Instance instance, PP_Bool main_service_runtime, const char* alleged_url, const struct PP_NaClFileInfo* nexe_file_info, PP_Bool uses_nonsfi_mode, PP_NaClAppProcessType process_type, void* imc_handle, struct PP_CompletionCallback callback))&Pnacl_M25_PPB_NaCl_Private_LaunchSelLdr, .UrandomFD = (int32_t (*)(void))&Pnacl_M25_PPB_NaCl_Private_UrandomFD, .BrokerDuplicateHandle = (int32_t (*)(PP_FileHandle source_handle, uint32_t process_id, PP_FileHandle* target_handle, uint32_t desired_access, uint32_t options))&Pnacl_M25_PPB_NaCl_Private_BrokerDuplicateHandle, .GetReadExecPnaclFd = (void (*)(const char* url, struct PP_NaClFileInfo* out_file_info))&Pnacl_M25_PPB_NaCl_Private_GetReadExecPnaclFd, @@ -5605,7 +5590,6 @@ .GetNumberOfProcessors = (int32_t (*)(void))&Pnacl_M25_PPB_NaCl_Private_GetNumberOfProcessors, .ReportTranslationFinished = (void (*)(PP_Instance instance, PP_Bool success, int32_t opt_level, int64_t pexe_size, int64_t compile_time_us))&Pnacl_M25_PPB_NaCl_Private_ReportTranslationFinished, .DispatchEvent = (void (*)(PP_Instance instance, PP_NaClEventType event_type, const char* resource_url, PP_Bool length_is_computable, uint64_t loaded_bytes, uint64_t total_bytes))&Pnacl_M25_PPB_NaCl_Private_DispatchEvent, - .ReportLoadSuccess = (void (*)(PP_Instance instance, uint64_t loaded_bytes, uint64_t total_bytes))&Pnacl_M25_PPB_NaCl_Private_ReportLoadSuccess, .ReportLoadError = (void (*)(PP_Instance instance, PP_NaClError error, const char* error_message))&Pnacl_M25_PPB_NaCl_Private_ReportLoadError, .InstanceCreated = (void (*)(PP_Instance instance))&Pnacl_M25_PPB_NaCl_Private_InstanceCreated, .InstanceDestroyed = (void (*)(PP_Instance instance))&Pnacl_M25_PPB_NaCl_Private_InstanceDestroyed, @@ -5615,14 +5599,12 @@ .RequestNaClManifest = (void (*)(PP_Instance instance, struct PP_CompletionCallback callback))&Pnacl_M25_PPB_NaCl_Private_RequestNaClManifest, .GetManifestBaseURL = (struct PP_Var (*)(PP_Instance instance))&Pnacl_M25_PPB_NaCl_Private_GetManifestBaseURL, .ProcessNaClManifest = (void (*)(PP_Instance instance, const char* program_url))&Pnacl_M25_PPB_NaCl_Private_ProcessNaClManifest, - .DevInterfacesEnabled = (PP_Bool (*)(PP_Instance instance))&Pnacl_M25_PPB_NaCl_Private_DevInterfacesEnabled, .GetManifestProgramURL = (PP_Bool (*)(PP_Instance instance, struct PP_Var* full_url, struct PP_PNaClOptions* pnacl_options, PP_Bool* uses_nonsfi_mode))&Pnacl_M25_PPB_NaCl_Private_GetManifestProgramURL, .GetPnaclResourceInfo = (PP_Bool (*)(PP_Instance instance, struct PP_Var* llc_tool_name, struct PP_Var* ld_tool_name))&Pnacl_M25_PPB_NaCl_Private_GetPnaclResourceInfo, .GetCpuFeatureAttrs = (struct PP_Var (*)(void))&Pnacl_M25_PPB_NaCl_Private_GetCpuFeatureAttrs, .DownloadNexe = (void (*)(PP_Instance instance, const char* url, struct PP_NaClFileInfo* file_info, struct PP_CompletionCallback callback))&Pnacl_M25_PPB_NaCl_Private_DownloadNexe, .ReportSelLdrStatus = (void (*)(PP_Instance instance, int32_t load_status, int32_t max_status))&Pnacl_M25_PPB_NaCl_Private_ReportSelLdrStatus, .LogTranslateTime = (void (*)(const char* histogram_name, int64_t time_us))&Pnacl_M25_PPB_NaCl_Private_LogTranslateTime, - .OpenManifestEntry = (void (*)(PP_Instance instance, PP_Bool is_helper_process, const char* key, struct PP_NaClFileInfo* file_info, struct PP_CompletionCallback callback))&Pnacl_M25_PPB_NaCl_Private_OpenManifestEntry, .SetPNaClStartTime = (void (*)(PP_Instance instance))&Pnacl_M25_PPB_NaCl_Private_SetPNaClStartTime, .StreamPexe = (void (*)(PP_Instance instance, const char* pexe_url, int32_t opt_level, const struct PPP_PexeStreamHandler_1_0* stream_handler, void* stream_handler_user_data))&Pnacl_M25_PPB_NaCl_Private_StreamPexe };
diff --git a/ppapi/native_client/src/untrusted/pnacl_support_extension/pnacl_support_extension.gyp b/ppapi/native_client/src/untrusted/pnacl_support_extension/pnacl_support_extension.gyp index dd58e1e83..9fadd74 100644 --- a/ppapi/native_client/src/untrusted/pnacl_support_extension/pnacl_support_extension.gyp +++ b/ppapi/native_client/src/untrusted/pnacl_support_extension/pnacl_support_extension.gyp
@@ -93,14 +93,12 @@ '<(PRODUCT_DIR)/pnacl/pnacl_public_x86_32_ld_nexe', '<(PRODUCT_DIR)/pnacl/pnacl_public_x86_32_libcrt_platform_a', '<(PRODUCT_DIR)/pnacl/pnacl_public_x86_32_libgcc_a', - '<(PRODUCT_DIR)/pnacl/pnacl_public_x86_32_libgcc_eh_a', '<(PRODUCT_DIR)/pnacl/pnacl_public_x86_32_libpnacl_irt_shim_a', '<(PRODUCT_DIR)/pnacl/pnacl_public_x86_32_pnacl_llc_nexe', '<(PRODUCT_DIR)/pnacl/pnacl_public_x86_64_crtbegin_o', '<(PRODUCT_DIR)/pnacl/pnacl_public_x86_64_ld_nexe', '<(PRODUCT_DIR)/pnacl/pnacl_public_x86_64_libcrt_platform_a', '<(PRODUCT_DIR)/pnacl/pnacl_public_x86_64_libgcc_a', - '<(PRODUCT_DIR)/pnacl/pnacl_public_x86_64_libgcc_eh_a', '<(PRODUCT_DIR)/pnacl/pnacl_public_x86_64_libpnacl_irt_shim_a', '<(PRODUCT_DIR)/pnacl/pnacl_public_x86_64_pnacl_llc_nexe', ], @@ -126,7 +124,6 @@ '<(PRODUCT_DIR)/pnacl/pnacl_public_arm_ld_nexe', '<(PRODUCT_DIR)/pnacl/pnacl_public_arm_libcrt_platform_a', '<(PRODUCT_DIR)/pnacl/pnacl_public_arm_libgcc_a', - '<(PRODUCT_DIR)/pnacl/pnacl_public_arm_libgcc_eh_a', '<(PRODUCT_DIR)/pnacl/pnacl_public_arm_libpnacl_irt_shim_a', '<(PRODUCT_DIR)/pnacl/pnacl_public_arm_pnacl_llc_nexe', ], @@ -147,7 +144,6 @@ '<(PRODUCT_DIR)/pnacl/pnacl_public_mips32_ld_nexe', '<(PRODUCT_DIR)/pnacl/pnacl_public_mips32_libcrt_platform_a', '<(PRODUCT_DIR)/pnacl/pnacl_public_mips32_libgcc_a', - '<(PRODUCT_DIR)/pnacl/pnacl_public_mips32_libgcc_eh_a', '<(PRODUCT_DIR)/pnacl/pnacl_public_mips32_libpnacl_irt_shim_a', '<(PRODUCT_DIR)/pnacl/pnacl_public_mips32_llc_nexe', ], @@ -168,7 +164,6 @@ '<(PRODUCT_DIR)/pnacl/pnacl_public_x86_32_ld_nexe', '<(PRODUCT_DIR)/pnacl/pnacl_public_x86_32_libcrt_platform_a', '<(PRODUCT_DIR)/pnacl/pnacl_public_x86_32_libgcc_a', - '<(PRODUCT_DIR)/pnacl/pnacl_public_x86_32_libgcc_eh_a', '<(PRODUCT_DIR)/pnacl/pnacl_public_x86_32_libpnacl_irt_shim_a', '<(PRODUCT_DIR)/pnacl/pnacl_public_x86_32_pnacl_llc_nexe', ], @@ -189,7 +184,6 @@ '<(PRODUCT_DIR)/pnacl/pnacl_public_x86_64_ld_nexe', '<(PRODUCT_DIR)/pnacl/pnacl_public_x86_64_libcrt_platform_a', '<(PRODUCT_DIR)/pnacl/pnacl_public_x86_64_libgcc_a', - '<(PRODUCT_DIR)/pnacl/pnacl_public_x86_64_libgcc_eh_a', '<(PRODUCT_DIR)/pnacl/pnacl_public_x86_64_libpnacl_irt_shim_a', '<(PRODUCT_DIR)/pnacl/pnacl_public_x86_64_pnacl_llc_nexe', ],
diff --git a/ppapi/tests/mojo/DEPS b/ppapi/tests/mojo/DEPS index ef8ad28..5f8633a 100644 --- a/ppapi/tests/mojo/DEPS +++ b/ppapi/tests/mojo/DEPS
@@ -1,3 +1,3 @@ include_rules = [ - "+mojo/public", + "+third_party/mojo/src/mojo/public", ]
diff --git a/ppapi/tests/mojo/test_mojo.cc b/ppapi/tests/mojo/test_mojo.cc index f49943eb..2743d06 100644 --- a/ppapi/tests/mojo/test_mojo.cc +++ b/ppapi/tests/mojo/test_mojo.cc
@@ -4,7 +4,7 @@ #include "ppapi/tests/mojo/test_mojo.h" -#include "mojo/public/cpp/system/message_pipe.h" +#include "third_party/mojo/src/mojo/public/cpp/system/message_pipe.h" REGISTER_TEST_CASE(Mojo);
diff --git a/ppapi/tests/test_view.cc b/ppapi/tests/test_view.cc index 5ce903a..df51199e 100644 --- a/ppapi/tests/test_view.cc +++ b/ppapi/tests/test_view.cc
@@ -14,7 +14,7 @@ REGISTER_TEST_CASE(View); // When waiting for view changed events, wait no longer than this. -#if !defined(THREAD_SANITIZER) +#if !defined(THREAD_SANITIZER) && !defined(MEMORY_SANITIZER) static int kViewChangeTimeoutSec = 5; #else // ThreadSanitizer may slow the interaction down significantly.
diff --git a/remoting/client/plugin/chromoting_instance.cc b/remoting/client/plugin/chromoting_instance.cc index ff8a06a..c75f57a 100644 --- a/remoting/client/plugin/chromoting_instance.cc +++ b/remoting/client/plugin/chromoting_instance.cc
@@ -198,8 +198,8 @@ // are not shared with Chrome. thread_task_runner_handle_.reset( new base::ThreadTaskRunnerHandle(plugin_task_runner_)); - thread_wrapper_.reset( - new jingle_glue::JingleThreadWrapper(plugin_task_runner_)); + thread_wrapper_ = + jingle_glue::JingleThreadWrapper::WrapTaskRunner(plugin_task_runner_); media::InitializeCPUSpecificYUVConversions(); // Register a global log handler. @@ -636,18 +636,21 @@ #endif input_handler_.set_input_stub(normalizing_input_filter_.get()); - // 3D renderer is currently disabled because it may be unstable. See - // crbug.com/447403 . - // - // video_renderer_.reset(new PepperVideoRenderer3D()); - // if (!video_renderer_->Initialize(this, context_, this)) - // video_renderer_.reset(); + // PPB_VideoDecoder is not always enabled because it's broken in some versions + // of Chrome. See crbug.com/447403 . + bool enable_video_decode_renderer = false; + if (data.GetBoolean("enableVideoDecodeRenderer", + &enable_video_decode_renderer) && + enable_video_decode_renderer) { + LOG(ERROR) << "Initializing 3D renderer."; + video_renderer_.reset(new PepperVideoRenderer3D()); + if (!video_renderer_->Initialize(this, context_, this)) + video_renderer_.reset(); + } - // If we failed to initialize 3D renderer (because there is no hardware - // support on this machine) then use the 2D renderer. + // If we didn't initialize 3D renderer then use the 2D renderer. if (!video_renderer_) { - LOG(WARNING) - << "Failed to initialize 3D renderer. Using 2D renderer instead."; + LOG(ERROR) << "Initializing 2D renderer."; video_renderer_.reset(new PepperVideoRenderer2D()); if (!video_renderer_->Initialize(this, context_, this)) video_renderer_.reset();
diff --git a/remoting/codec/video_encoder_vpx.cc b/remoting/codec/video_encoder_vpx.cc index fc2b27a..73e8ee8 100644 --- a/remoting/codec/video_encoder_vpx.cc +++ b/remoting/codec/video_encoder_vpx.cc
@@ -383,13 +383,16 @@ return; } - // Align the region to macroblocks, to avoid encoding artefacts. - // If VP9 is in use then we also pad the rectangles before aligning them, to - // avoid edge artefacts. - // This also ensures that all rectangles have even-aligned top-left, which - // is required for ConvertRGBToYUVWithRect() to work. + // Pad each rectangle to avoid the block-artefact filters in libvpx from + // introducing artefacts; VP9 includes up to 8px either side, and VP8 up to + // 3px, so unchanged pixels up to that far out may still be affected by the + // changes in the updated region, and so must be listed in the active map. + // After padding we align each rectangle to 16x16 active-map macroblocks. + // This implicitly ensures all rects have even top-left coords, which is + // is required by ConvertRGBToYUVWithRect(). + // TODO(wez): Do we still need 16x16 align, or is even alignment sufficient? updated_region->Clear(); - int padding = use_vp9_ ? 8 : 0; + int padding = use_vp9_ ? 8 : 3; for (webrtc::DesktopRegion::Iterator r(frame.updated_region()); !r.IsAtEnd(); r.Advance()) { const webrtc::DesktopRect& rect = r.rect();
diff --git a/remoting/host/policy_hack/fake_policy_watcher.cc b/remoting/host/policy_hack/fake_policy_watcher.cc deleted file mode 100644 index e80c6762..0000000 --- a/remoting/host/policy_hack/fake_policy_watcher.cc +++ /dev/null
@@ -1,35 +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 "remoting/host/policy_hack/fake_policy_watcher.h" - -#include "base/single_thread_task_runner.h" - -namespace remoting { -namespace policy_hack { - -FakePolicyWatcher::FakePolicyWatcher( - scoped_refptr<base::SingleThreadTaskRunner> task_runner) - : PolicyWatcher(task_runner) { -} - -FakePolicyWatcher::~FakePolicyWatcher() { -} - -void FakePolicyWatcher::SetPolicies(const base::DictionaryValue* policies) { - UpdatePolicies(policies); -} - -void FakePolicyWatcher::SignalTransientErrorForTest() { - SignalTransientPolicyError(); -} - -void FakePolicyWatcher::StartWatchingInternal() { -} - -void FakePolicyWatcher::StopWatchingInternal() { -} - -} // namespace policy_hack -} // namespace remoting
diff --git a/remoting/host/policy_hack/fake_policy_watcher.h b/remoting/host/policy_hack/fake_policy_watcher.h deleted file mode 100644 index a8bf491b..0000000 --- a/remoting/host/policy_hack/fake_policy_watcher.h +++ /dev/null
@@ -1,31 +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 REMOTING_HOST_POLICY_HACK_FAKE_POLICY_WATCHER_H_ -#define REMOTING_HOST_POLICY_HACK_FAKE_POLICY_WATCHER_H_ - -#include "remoting/host/policy_hack/policy_watcher.h" - -namespace remoting { -namespace policy_hack { - -class FakePolicyWatcher : public PolicyWatcher { - public: - explicit FakePolicyWatcher( - scoped_refptr<base::SingleThreadTaskRunner> task_runner); - ~FakePolicyWatcher() override; - - void SetPolicies(const base::DictionaryValue* policies); - - void SignalTransientErrorForTest(); - - protected: - void StartWatchingInternal() override; - void StopWatchingInternal() override; -}; - -} // namespace policy_hack -} // namespace remoting - -#endif // REMOTING_HOST_POLICY_HACK_FAKE_POLICY_WATCHER_H_
diff --git a/remoting/host/policy_hack/policy_service_watcher.cc b/remoting/host/policy_hack/policy_service_watcher.cc index 08cb78c..50744c1 100644 --- a/remoting/host/policy_hack/policy_service_watcher.cc +++ b/remoting/host/policy_hack/policy_service_watcher.cc
@@ -2,17 +2,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "remoting/host/policy_hack/policy_service_watcher.h" + #include "base/files/file_path.h" -#include "base/single_thread_task_runner.h" +#include "base/values.h" #include "components/policy/core/common/async_policy_loader.h" #include "components/policy/core/common/async_policy_provider.h" #include "components/policy/core/common/policy_namespace.h" -#include "components/policy/core/common/policy_service.h" #include "components/policy/core/common/policy_service_impl.h" #include "components/policy/core/common/schema.h" #include "components/policy/core/common/schema_registry.h" #include "policy/policy_constants.h" -#include "remoting/host/policy_hack/policy_watcher.h" #if defined(OS_CHROMEOS) #include "content/public/browser/browser_thread.h" @@ -32,69 +32,12 @@ namespace { -// TODO(lukasza): Merge PolicyServiceWatcher with PolicyWatcher class -// (after removing other classes derived from PolicyWatcher - i.e. after -// removing FakePolicyWatcher class and replacing it with mocks of classes -// from components/policy instead). - -// PolicyServiceWatcher is a concrete implementation of PolicyWatcher that wraps -// an instance of PolicyService. -class PolicyServiceWatcher : public PolicyWatcher, - public PolicyService::Observer { - public: - // Constructor for the case when |policy_service| is borrowed. - // - // |policy_service_task_runner| is the task runner where it is safe - // to call |policy_service| methods and where we expect to get callbacks - // from |policy_service|. - PolicyServiceWatcher(const scoped_refptr<base::SingleThreadTaskRunner>& - policy_service_task_runner, - PolicyService* policy_service); - - // Constructor for the case when |policy_service| is owned (and uses also - // owned |owned_policy_provider| and |owned_schema_registry|. - // - // |policy_service_task_runner| is the task runner where it is safe - // to call |policy_service| methods and where we expect to get callbacks - // from |policy_service|. - PolicyServiceWatcher( - const scoped_refptr<base::SingleThreadTaskRunner>& - policy_service_task_runner, - scoped_ptr<PolicyService> owned_policy_service, - scoped_ptr<ConfigurationPolicyProvider> owned_policy_provider, - scoped_ptr<SchemaRegistry> owned_schema_registry); - - ~PolicyServiceWatcher() override; - - // PolicyService::Observer interface. - void OnPolicyUpdated(const PolicyNamespace& ns, - const PolicyMap& previous, - const PolicyMap& current) override; - void OnPolicyServiceInitialized(PolicyDomain domain) override; - - protected: - // PolicyWatcher overrides. - void StartWatchingInternal() override; - void StopWatchingInternal() override; - - private: - PolicyService* policy_service_; - - // Order of fields below is important to ensure destruction takes object - // dependencies into account: - // - |owned_policy_service_| uses |owned_policy_provider_| - // - |owned_policy_provider_| uses |owned_schema_registry_| - scoped_ptr<SchemaRegistry> owned_schema_registry_; - scoped_ptr<ConfigurationPolicyProvider> owned_policy_provider_; - scoped_ptr<PolicyService> owned_policy_service_; - - DISALLOW_COPY_AND_ASSIGN(PolicyServiceWatcher); -}; - PolicyNamespace GetPolicyNamespace() { return PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()); } +} // namespace + PolicyServiceWatcher::PolicyServiceWatcher( const scoped_refptr<base::SingleThreadTaskRunner>& policy_service_task_runner, @@ -154,14 +97,7 @@ policy_service_->RemoveObserver(POLICY_DOMAIN_CHROME, this); } -#if !defined(OS_CHROMEOS) - -// Creates PolicyServiceWatcher that wraps the owned |async_policy_loader| -// with an appropriate PolicySchema. -// -// |policy_service_task_runner| is passed through to the constructor -// of PolicyServiceWatcher. -scoped_ptr<PolicyServiceWatcher> CreateFromPolicyLoader( +scoped_ptr<PolicyServiceWatcher> PolicyServiceWatcher::CreateFromPolicyLoader( const scoped_refptr<base::SingleThreadTaskRunner>& policy_service_task_runner, scoped_ptr<AsyncPolicyLoader> async_policy_loader) { @@ -186,10 +122,6 @@ schema_registry.Pass())); } -#endif - -} // anonymous namespace - scoped_ptr<PolicyWatcher> PolicyWatcher::Create( policy::PolicyService* policy_service, const scoped_refptr<base::SingleThreadTaskRunner>& network_task_runner) { @@ -202,13 +134,13 @@ #elif defined(OS_WIN) DCHECK(!policy_service); static const wchar_t kRegistryKey[] = L"SOFTWARE\\Policies\\Google\\Chrome"; - return CreateFromPolicyLoader( + return PolicyServiceWatcher::CreateFromPolicyLoader( network_task_runner, PolicyLoaderWin::Create(network_task_runner, kRegistryKey)); #elif defined(OS_MACOSX) CFStringRef bundle_id = CFSTR("com.google.Chrome"); DCHECK(!policy_service); - return CreateFromPolicyLoader( + return PolicyServiceWatcher::CreateFromPolicyLoader( network_task_runner, make_scoped_ptr(new PolicyLoaderMac( network_task_runner, @@ -220,7 +152,7 @@ // enforcement can't be bypassed by running Chromium. static const base::FilePath::CharType kPolicyDir[] = FILE_PATH_LITERAL("/etc/opt/chrome/policies"); - return CreateFromPolicyLoader( + return PolicyServiceWatcher::CreateFromPolicyLoader( network_task_runner, make_scoped_ptr(new ConfigDirPolicyLoader( network_task_runner, base::FilePath(kPolicyDir), POLICY_SCOPE_MACHINE)));
diff --git a/remoting/host/policy_hack/policy_service_watcher.h b/remoting/host/policy_hack/policy_service_watcher.h new file mode 100644 index 0000000..37e4a51d --- /dev/null +++ b/remoting/host/policy_hack/policy_service_watcher.h
@@ -0,0 +1,96 @@ +// Copyright 2015 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 REMOTING_HOST_POLICY_HACK_POLICY_SERVICE_WATCHER_H_ +#define REMOTING_HOST_POLICY_HACK_POLICY_SERVICE_WATCHER_H_ + +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "components/policy/core/common/policy_service.h" +#include "remoting/host/policy_hack/policy_watcher.h" + +namespace base { +class SingleThreadTaskRunner; +} // namespace base + +namespace policy { +class AsyncPolicyLoader; +class ConfigurationPolicyProvider; +class SchemaRegistry; +} // namespace policy + +namespace remoting { +namespace policy_hack { + +// TODO(lukasza): Merge PolicyServiceWatcher with PolicyWatcher class. + +// PolicyServiceWatcher is a concrete implementation of PolicyWatcher that wraps +// an instance of PolicyService. +class PolicyServiceWatcher : public PolicyWatcher, + public policy::PolicyService::Observer { + public: + // Constructor for the case when |policy_service| is borrowed. + // + // |policy_service_task_runner| is the task runner where it is safe + // to call |policy_service| methods and where we expect to get callbacks + // from |policy_service|. + PolicyServiceWatcher(const scoped_refptr<base::SingleThreadTaskRunner>& + policy_service_task_runner, + policy::PolicyService* policy_service); + + // Constructor for the case when |policy_service| is owned (and uses also + // owned |owned_policy_provider| and |owned_schema_registry|. + // + // |policy_service_task_runner| is the task runner where it is safe + // to call |policy_service| methods and where we expect to get callbacks + // from |policy_service|. + PolicyServiceWatcher( + const scoped_refptr<base::SingleThreadTaskRunner>& + policy_service_task_runner, + scoped_ptr<policy::PolicyService> owned_policy_service, + scoped_ptr<policy::ConfigurationPolicyProvider> owned_policy_provider, + scoped_ptr<policy::SchemaRegistry> owned_schema_registry); + + ~PolicyServiceWatcher() override; + + // Creates PolicyServiceWatcher that wraps the owned |async_policy_loader| + // with an appropriate PolicySchema. + // + // |policy_service_task_runner| is passed through to the constructor + // of PolicyServiceWatcher. + static scoped_ptr<PolicyServiceWatcher> CreateFromPolicyLoader( + const scoped_refptr<base::SingleThreadTaskRunner>& + policy_service_task_runner, + scoped_ptr<policy::AsyncPolicyLoader> async_policy_loader); + + // PolicyService::Observer interface. + void OnPolicyUpdated(const policy::PolicyNamespace& ns, + const policy::PolicyMap& previous, + const policy::PolicyMap& current) override; + void OnPolicyServiceInitialized(policy::PolicyDomain domain) override; + + protected: + // PolicyWatcher overrides. + void StartWatchingInternal() override; + void StopWatchingInternal() override; + + private: + policy::PolicyService* policy_service_; + + // Order of fields below is important to ensure destruction takes object + // dependencies into account: + // - |owned_policy_service_| uses |owned_policy_provider_| + // - |owned_policy_provider_| uses |owned_schema_registry_| + scoped_ptr<policy::SchemaRegistry> owned_schema_registry_; + scoped_ptr<policy::ConfigurationPolicyProvider> owned_policy_provider_; + scoped_ptr<policy::PolicyService> owned_policy_service_; + + DISALLOW_COPY_AND_ASSIGN(PolicyServiceWatcher); +}; + +} // namespace policy_hack +} // namespace remoting + +#endif // REMOTING_HOST_POLICY_HACK_POLICY_SERVICE_WATCHER_H_
diff --git a/remoting/host/policy_hack/policy_watcher.h b/remoting/host/policy_hack/policy_watcher.h index 408d6c52..15254b5 100644 --- a/remoting/host/policy_hack/policy_watcher.h +++ b/remoting/host/policy_hack/policy_watcher.h
@@ -114,6 +114,8 @@ // The counter is reset whenever policy has been successfully read. void SignalTransientPolicyError(); + friend class PolicyWatcherTest; + // Returns a DictionaryValue containing the default values for each policy. const base::DictionaryValue& Defaults() const;
diff --git a/remoting/host/policy_hack/policy_watcher_unittest.cc b/remoting/host/policy_hack/policy_watcher_unittest.cc index e4b8554..84adca2c 100644 --- a/remoting/host/policy_hack/policy_watcher_unittest.cc +++ b/remoting/host/policy_hack/policy_watcher_unittest.cc
@@ -4,13 +4,15 @@ #include "base/basictypes.h" #include "base/bind.h" +#include "base/json/json_writer.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/synchronization/waitable_event.h" +#include "components/policy/core/common/fake_async_policy_loader.h" #include "policy/policy_constants.h" #include "remoting/host/dns_blackhole_checker.h" -#include "remoting/host/policy_hack/fake_policy_watcher.h" #include "remoting/host/policy_hack/mock_policy_callback.h" +#include "remoting/host/policy_hack/policy_service_watcher.h" #include "remoting/host/policy_hack/policy_watcher.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -30,7 +32,12 @@ policy_error_callback_ = base::Bind( &MockPolicyCallback::OnPolicyError, base::Unretained(&mock_policy_callback_)); - policy_watcher_.reset(new FakePolicyWatcher(message_loop_proxy_)); + + // Retaining a raw pointer to keep control over policy contents. + policy_loader_ = new policy::FakeAsyncPolicyLoader(message_loop_proxy_); + policy_watcher_ = PolicyServiceWatcher::CreateFromPolicyLoader( + message_loop_proxy_, make_scoped_ptr(policy_loader_)); + nat_true_.SetBoolean(policy::key::kRemoteAccessHostFirewallTraversal, true); nat_false_.SetBoolean(policy::key::kRemoteAccessHostFirewallTraversal, false); @@ -108,6 +115,12 @@ #endif } + void TearDown() override { + policy_watcher_.reset(); + policy_loader_ = nullptr; + base::RunLoop().RunUntilIdle(); + } + protected: void StartWatching() { policy_watcher_->StartWatching( @@ -123,6 +136,25 @@ base::RunLoop().RunUntilIdle(); } + void SetPolicies(const base::DictionaryValue& dict) { + // Copy |dict| into |policy_bundle|. + policy::PolicyNamespace policy_namespace = + policy::PolicyNamespace(policy::POLICY_DOMAIN_CHROME, std::string()); + policy::PolicyBundle policy_bundle; + policy::PolicyMap& policy_map = policy_bundle.Get(policy_namespace); + policy_map.LoadFrom(&dict, policy::POLICY_LEVEL_MANDATORY, + policy::POLICY_SCOPE_MACHINE); + + // Simulate a policy file/registry/preference update. + policy_loader_->SetPolicies(policy_bundle); + policy_loader_->PostReloadOnBackgroundThread(true /* force reload asap */); + base::RunLoop().RunUntilIdle(); + } + + void SignalTransientErrorForTest() { + policy_watcher_->SignalTransientPolicyError(); + } + MOCK_METHOD0(PostPolicyWatcherShutdown, void()); static const char* kHostDomain; @@ -132,7 +164,13 @@ MockPolicyCallback mock_policy_callback_; PolicyWatcher::PolicyUpdatedCallback policy_updated_callback_; PolicyWatcher::PolicyErrorCallback policy_error_callback_; - scoped_ptr<FakePolicyWatcher> policy_watcher_; + + // |policy_loader_| is owned by |policy_watcher_|. PolicyWatcherTest retains + // a raw pointer to |policy_loader_| in order to control the simulated / faked + // policy contents. + policy::FakeAsyncPolicyLoader* policy_loader_; + scoped_ptr<PolicyWatcher> policy_watcher_; + base::DictionaryValue empty_; base::DictionaryValue nat_true_; base::DictionaryValue nat_false_; @@ -189,15 +227,29 @@ const char* PolicyWatcherTest::kPortRange = "12400-12409"; MATCHER_P(IsPolicies, dict, "") { - return arg->Equals(dict); + bool equal = arg->Equals(dict); + if (!equal) { + std::string actual_value; + base::JSONWriter::WriteWithOptions( + arg, base::JSONWriter::OPTIONS_PRETTY_PRINT, &actual_value); + + std::string expected_value; + base::JSONWriter::WriteWithOptions( + dict, base::JSONWriter::OPTIONS_PRETTY_PRINT, &expected_value); + + *result_listener << "Policies are not equal. "; + *result_listener << "Expected policy: " << expected_value << ". "; + *result_listener << "Actual policy: " << actual_value << "."; + } + return equal; } TEST_F(PolicyWatcherTest, None) { EXPECT_CALL(mock_policy_callback_, OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_))); + SetPolicies(empty_); StartWatching(); - policy_watcher_->SetPolicies(&empty_); StopWatching(); } @@ -205,8 +257,8 @@ EXPECT_CALL(mock_policy_callback_, OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_))); + SetPolicies(nat_true_); StartWatching(); - policy_watcher_->SetPolicies(&nat_true_); StopWatching(); } @@ -214,8 +266,8 @@ EXPECT_CALL(mock_policy_callback_, OnPolicyUpdatePtr(IsPolicies(&nat_false_others_default_))); + SetPolicies(nat_false_); StartWatching(); - policy_watcher_->SetPolicies(&nat_false_); StopWatching(); } @@ -223,8 +275,8 @@ EXPECT_CALL(mock_policy_callback_, OnPolicyUpdatePtr(IsPolicies(&nat_false_others_default_))); + SetPolicies(nat_one_); StartWatching(); - policy_watcher_->SetPolicies(&nat_one_); StopWatching(); } @@ -232,8 +284,8 @@ EXPECT_CALL(mock_policy_callback_, OnPolicyUpdatePtr(IsPolicies(&domain_empty_others_default_))); + SetPolicies(domain_empty_); StartWatching(); - policy_watcher_->SetPolicies(&domain_empty_); StopWatching(); } @@ -241,8 +293,8 @@ EXPECT_CALL(mock_policy_callback_, OnPolicyUpdatePtr(IsPolicies(&domain_full_others_default_))); + SetPolicies(domain_full_); StartWatching(); - policy_watcher_->SetPolicies(&domain_full_); StopWatching(); } @@ -250,9 +302,9 @@ EXPECT_CALL(mock_policy_callback_, OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_))); + SetPolicies(empty_); StartWatching(); - policy_watcher_->SetPolicies(&empty_); - policy_watcher_->SetPolicies(&nat_true_); + SetPolicies(nat_true_); StopWatching(); } @@ -260,10 +312,10 @@ EXPECT_CALL(mock_policy_callback_, OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_))); + SetPolicies(empty_); StartWatching(); - policy_watcher_->SetPolicies(&empty_); - policy_watcher_->SetPolicies(&nat_true_); - policy_watcher_->SetPolicies(&nat_true_); + SetPolicies(nat_true_); + SetPolicies(nat_true_); StopWatching(); } @@ -274,11 +326,11 @@ EXPECT_CALL(mock_policy_callback_, OnPolicyUpdatePtr(IsPolicies(&nat_false_))); + SetPolicies(empty_); StartWatching(); - policy_watcher_->SetPolicies(&empty_); - policy_watcher_->SetPolicies(&nat_true_); - policy_watcher_->SetPolicies(&nat_true_); - policy_watcher_->SetPolicies(&nat_false_); + SetPolicies(nat_true_); + SetPolicies(nat_true_); + SetPolicies(nat_false_); StopWatching(); } @@ -289,9 +341,9 @@ EXPECT_CALL(mock_policy_callback_, OnPolicyUpdatePtr(IsPolicies(&nat_false_))); + SetPolicies(empty_); StartWatching(); - policy_watcher_->SetPolicies(&empty_); - policy_watcher_->SetPolicies(&nat_false_); + SetPolicies(nat_false_); StopWatching(); } @@ -304,10 +356,10 @@ EXPECT_CALL(mock_policy_callback_, OnPolicyUpdatePtr(IsPolicies(&nat_true_))); + SetPolicies(empty_); StartWatching(); - policy_watcher_->SetPolicies(&empty_); - policy_watcher_->SetPolicies(&nat_false_); - policy_watcher_->SetPolicies(&nat_true_); + SetPolicies(nat_false_); + SetPolicies(nat_true_); StopWatching(); } @@ -325,12 +377,12 @@ EXPECT_CALL(mock_policy_callback_, OnPolicyUpdatePtr(IsPolicies(&nat_true_domain_full_))); + SetPolicies(nat_true_domain_empty_); StartWatching(); - policy_watcher_->SetPolicies(&nat_true_domain_empty_); - policy_watcher_->SetPolicies(&nat_true_domain_full_); - policy_watcher_->SetPolicies(&nat_false_domain_full_); - policy_watcher_->SetPolicies(&nat_false_domain_empty_); - policy_watcher_->SetPolicies(&nat_true_domain_full_); + SetPolicies(nat_true_domain_full_); + SetPolicies(nat_false_domain_full_); + SetPolicies(nat_false_domain_empty_); + SetPolicies(nat_true_domain_full_); StopWatching(); } @@ -339,24 +391,25 @@ EXPECT_CALL(mock_policy_callback_, OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_))); + SetPolicies(empty_); StartWatching(); - policy_watcher_->SetPolicies(&empty_); - policy_watcher_->SetPolicies(&unknown_policies_); - policy_watcher_->SetPolicies(&empty_); + SetPolicies(unknown_policies_); + SetPolicies(empty_); StopWatching(); } TEST_F(PolicyWatcherTest, DebugOverrideNatPolicy) { #if !defined(NDEBUG) - EXPECT_CALL(mock_policy_callback_, + EXPECT_CALL( + mock_policy_callback_, OnPolicyUpdatePtr(IsPolicies(&nat_false_overridden_others_default_))); #else EXPECT_CALL(mock_policy_callback_, - OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_))); + OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_))); #endif + SetPolicies(nat_true_and_overridden_); StartWatching(); - policy_watcher_->SetPolicies(&nat_true_and_overridden_); StopWatching(); } @@ -369,10 +422,10 @@ EXPECT_CALL(mock_policy_callback_, OnPolicyUpdatePtr(IsPolicies(&pairing_true_))); + SetPolicies(empty_); StartWatching(); - policy_watcher_->SetPolicies(&empty_); - policy_watcher_->SetPolicies(&pairing_false_); - policy_watcher_->SetPolicies(&pairing_true_); + SetPolicies(pairing_false_); + SetPolicies(pairing_true_); StopWatching(); } @@ -385,10 +438,10 @@ EXPECT_CALL(mock_policy_callback_, OnPolicyUpdatePtr(IsPolicies(&gnubby_auth_true_))); + SetPolicies(empty_); StartWatching(); - policy_watcher_->SetPolicies(&empty_); - policy_watcher_->SetPolicies(&gnubby_auth_false_); - policy_watcher_->SetPolicies(&gnubby_auth_true_); + SetPolicies(gnubby_auth_false_); + SetPolicies(gnubby_auth_true_); StopWatching(); } @@ -401,10 +454,10 @@ EXPECT_CALL(mock_policy_callback_, OnPolicyUpdatePtr(IsPolicies(&relay_true_))); + SetPolicies(empty_); StartWatching(); - policy_watcher_->SetPolicies(&empty_); - policy_watcher_->SetPolicies(&relay_false_); - policy_watcher_->SetPolicies(&relay_true_); + SetPolicies(relay_false_); + SetPolicies(relay_true_); StopWatching(); } @@ -417,10 +470,10 @@ EXPECT_CALL(mock_policy_callback_, OnPolicyUpdatePtr(IsPolicies(&port_range_empty_))); + SetPolicies(empty_); StartWatching(); - policy_watcher_->SetPolicies(&empty_); - policy_watcher_->SetPolicies(&port_range_full_); - policy_watcher_->SetPolicies(&port_range_empty_); + SetPolicies(port_range_full_); + SetPolicies(port_range_empty_); StopWatching(); } @@ -430,7 +483,7 @@ EXPECT_CALL(mock_policy_callback_, OnPolicyErrorPtr()).Times(0); StartWatching(); - policy_watcher_->SignalTransientErrorForTest(); + SignalTransientErrorForTest(); StopWatching(); } @@ -439,24 +492,23 @@ StartWatching(); for (int i = 0; i < kMaxTransientErrorRetries; i++) { - policy_watcher_->SignalTransientErrorForTest(); + SignalTransientErrorForTest(); } StopWatching(); } TEST_F(PolicyWatcherTest, PolicyUpdateResetsTransientErrorsCounter) { testing::InSequence s; - EXPECT_CALL(mock_policy_callback_, - OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_))); + EXPECT_CALL(mock_policy_callback_, OnPolicyUpdatePtr(testing::_)); EXPECT_CALL(mock_policy_callback_, OnPolicyErrorPtr()).Times(0); StartWatching(); for (int i = 0; i < (kMaxTransientErrorRetries - 1); i++) { - policy_watcher_->SignalTransientErrorForTest(); + SignalTransientErrorForTest(); } - policy_watcher_->SetPolicies(&nat_true_); + SetPolicies(nat_true_); for (int i = 0; i < (kMaxTransientErrorRetries - 1); i++) { - policy_watcher_->SignalTransientErrorForTest(); + SignalTransientErrorForTest(); } StopWatching(); } @@ -530,8 +582,5 @@ #endif -// TODO(lukasza): We should consider adding a test against a -// MockConfigurationPolicyProvider. - } // namespace policy_hack } // namespace remoting
diff --git a/remoting/remoting_client.gypi b/remoting/remoting_client.gypi index 59da698..cf54377d 100644 --- a/remoting/remoting_client.gypi +++ b/remoting/remoting_client.gypi
@@ -116,6 +116,13 @@ 'remoting_webapp_v1', 'remoting_webapp_v2', ], + 'conditions': [ + ['disable_nacl==0 and disable_nacl_untrusted==0', { + 'dependencies': [ + 'remoting_webapp_v2_pnacl', + ], + }] + ], }, # end of target 'remoting_webapp' { @@ -135,26 +142,33 @@ 'variables': { 'output_dir': '<(PRODUCT_DIR)/remoting/remoting.webapp.v2', 'zip_path': '<(PRODUCT_DIR)/remoting-webapp.v2.zip', + 'webapp_type': 'v2', }, - 'conditions': [ - ['disable_nacl==0 and disable_nacl_untrusted==0', { - 'dependencies': [ - 'remoting_nacl.gyp:remoting_client_plugin_nacl', - ], + 'includes': [ 'remoting_webapp.gypi', ], + }, # end of target 'remoting_webapp_v2' + ], # end of targets + + 'conditions': [ + ['disable_nacl==0 and disable_nacl_untrusted==0', { + 'targets': [ + { + 'target_name': 'remoting_webapp_v2_pnacl', + 'type': 'none', 'variables': { + 'output_dir': '<(PRODUCT_DIR)/remoting/remoting.webapp.v2_pnacl', + 'zip_path': '<(PRODUCT_DIR)/remoting-webapp.v2_pnacl.zip', 'webapp_type': 'v2_pnacl', 'extra_files': [ 'webapp/crd/remoting_client_pnacl.nmf', '<(PRODUCT_DIR)/remoting_client_plugin_newlib.pexe', ], }, - }, { - 'variables': { - 'webapp_type': 'v2', - }, - }], + 'dependencies': [ + 'remoting_nacl.gyp:remoting_client_plugin_nacl', + ], + 'includes': [ 'remoting_webapp.gypi', ], + }, # end of target 'remoting_webapp_v2_pnacl' ], - 'includes': [ 'remoting_webapp.gypi', ], - }, # end of target 'remoting_webapp_v2' - ], # end of targets + }], + ], }
diff --git a/remoting/remoting_host_srcs.gypi b/remoting/remoting_host_srcs.gypi index c3a7a8b..4d5d628 100644 --- a/remoting/remoting_host_srcs.gypi +++ b/remoting/remoting_host_srcs.gypi
@@ -190,6 +190,7 @@ 'host/policy_hack/policy_watcher.cc', 'host/policy_hack/policy_watcher.h', 'host/policy_hack/policy_service_watcher.cc', + 'host/policy_hack/policy_service_watcher.h', 'host/register_support_host_request.cc', 'host/register_support_host_request.h', 'host/remote_input_filter.cc',
diff --git a/remoting/remoting_test.gypi b/remoting/remoting_test.gypi index 06c1e6c..043b22c 100644 --- a/remoting/remoting_test.gypi +++ b/remoting/remoting_test.gypi
@@ -9,6 +9,7 @@ 'type': 'static_library', 'dependencies': [ '../base/base.gyp:base', + '../components/components.gyp:policy_component_test_support', '../net/net.gyp:net_test_support', '../testing/gmock.gyp:gmock', '../testing/gtest.gyp:gtest', @@ -26,8 +27,6 @@ 'host/fake_host_status_monitor.h', 'host/fake_mouse_cursor_monitor.cc', 'host/fake_mouse_cursor_monitor.h', - 'host/policy_hack/fake_policy_watcher.cc', - 'host/policy_hack/fake_policy_watcher.h', 'host/policy_hack/mock_policy_callback.cc', 'host/policy_hack/mock_policy_callback.h', 'protocol/fake_authenticator.cc',
diff --git a/remoting/resources/remoting_strings.grd b/remoting/resources/remoting_strings.grd index d78d8e3..b026b41b 100644 --- a/remoting/resources/remoting_strings.grd +++ b/remoting/resources/remoting_strings.grd
@@ -261,6 +261,7 @@ </translations> <release allow_pseudo="false" seq="1"> <messages fallback_to_english="true"> + <if expr="_google_chrome"> <if expr="is_android or is_ios"> <message desc="Message shown in popup dialog on Android when there are no Google accounts on the device" name="IDS_NOACCOUNTS_MESSAGE" formatter_data="android_java"> @@ -269,14 +270,11 @@ <message desc="The product name, as displayed on Android devices. Ideally this would be 'Chrome Remote Desktop', but that name is too long to be displayed in the Android Launcher. Try to keep the translation below 16 characters if possible." name="IDS_PRODUCT_NAME_ANDROID" formatter_data="android_java"> Remote Desktop </message> - </if> + </if> <!-- is_android or is_ios --> <message desc="Message shown when the Chrome Remote Desktop client tab is closed while a connection is active." name="IDS_CLOSE_PROMPT"> Leaving this page will end your Chrome Remote Desktop session. </message> - <message desc="Text shown when the app first starts, or if the access token is invalidated, explaining the need to authorize the Chrome Remote Desktop app before use." name="IDS_DESCRIPTION_AUTHORIZE"> - To use Chrome Remote Desktop you must grant extended access permissions to your computer. You only have to do this once. - </message> <message desc="Confirmation prompt shown when a user needs to authenticate against a third party, explaining the need to authorize the Chrome Remote Desktop app to access the authentication URL." name="IDS_DESCRIPTION_THIRD_PARTY_AUTH"> The remote host requires you to authenticate to a third-party website. To continue, you must grant Chrome Remote Desktop additional permissions to access this address: </message> @@ -286,24 +284,12 @@ <message desc="Error displayed if authentication fails. This can be caused by stale credentials, in which logging out of the web-app and retrying can fix the problem." name="IDS_ERROR_AUTHENTICATION_FAILED" formatter_data="android_java"> Authentication failed. Please sign in to Chrome Remote Desktop again. </message> - <message desc="Error displayed if the client plugin are missing or if they could not be loaded." name="IDS_ERROR_BAD_PLUGIN_VERSION"> - Some components required for Chrome Remote Desktop are missing. Please make sure you have installed the latest version and try again. - </message> - <message desc="Error that is shown on the client side when incompatible Chrome Remote Desktop versions are installed on host and client." name="IDS_ERROR_INCOMPATIBLE_PROTOCOL" formatter_data="android_java"> - An incompatible version of Chrome Remote Desktop was detected. Please make sure that you have the latest version of Chrome and Chrome Remote Desktop on both computers and try again. - </message> <message desc="Error displayed when the computer has a policy that only users in a particular domain may use it as a Chrome Remote Desktop host, and a user in a different domain is trying to use it as a Chrome Remote Desktop host." name="IDS_ERROR_INVALID_HOST_DOMAIN"> Policy settings do not permit sharing this computer as a Chrome Remote Desktop host. Contact your system administrator for assistance. </message> <message desc="Error displayed when an operation is attempted that requires a signed-in user, but no-one is currently signed in." name="IDS_ERROR_NOT_AUTHENTICATED"> You are not signed in to Chrome Remote Desktop. Please sign in and try again. </message> - <message desc="Error displayed when a user attempts to connect to an application that they have not been authorized to access." name="IDS_ERROR_NOT_AUTHORIZED"> - You are not authorized to access this application. - </message> - <message desc="Error displayed if the client plugin fails to load." name="IDS_ERROR_MISSING_PLUGIN"> - Some components required for Chrome Remote Desktop are missing. Please make sure you're running the latest version of Chrome and try again. - </message> <message desc="Message displayed when the current computer is accepting remote connections." name="IDS_HOME_DAEMON_ACTIVE_MESSAGE"> You may securely access this computer using Chrome Remote Desktop. </message> @@ -331,6 +317,9 @@ <message desc="The product name. Displayed in various Chrome pages, including the New Tab page, and displayed prominently on the app's main page." name="IDS_PRODUCT_NAME"> Chrome Remote Desktop </message> + <message desc="The product name. Displayed in various Chrome pages, including the New Tab page, and displayed prominently on the app's main page." name="IDS_PRODUCT_NAME_APP_STREAMING"> + Chrome App Streaming + </message> <message desc="Message displayed at the bottom of the client connect dialog if Chrome Remote Desktop is running in the wrong start-up mode." name="IDS_WARNING_NOT_WINDOWED"> NOTE: To ensure that all keyboard shortcuts are available, you can configure Chrome Remote Desktop to ‘Open as window’. </message> @@ -367,7 +356,7 @@ <message name="IDS_MAC_UNINSTALLER_BUNDLE_NAME" desc="The bundle name specified in the property list of Chrome Remote Desktop Host Uninstaller bundle on MacOS."> Chrome Remote Desktop Host Uninstaller </message> - </if> + </if> <!-- _google_chrome --> <if expr="not _google_chrome"> <if expr="is_android or is_ios"> @@ -377,14 +366,11 @@ <message desc="The product name, as displayed on Android devices. Try to keep the translation below 16 characters if possible." name="IDS_PRODUCT_NAME_ANDROID" formatter_data="android_java"> Chromoting </message> - </if> + </if> <!-- is_android or is_ios --> <message desc="Message shown when the Chromoting client tab is closed while a connection is active." name="IDS_CLOSE_PROMPT"> Leaving this page will end your Chromoting session. </message> - <message desc="Text shown when the app first starts, or if the access token is invalidated, explaining the need to authorize the Chromoting app before use." name="IDS_DESCRIPTION_AUTHORIZE"> - To use Chromoting you must grant extended access permissions to your computer. You only have to do this once. - </message> <message desc="Confirmation prompt shown when a user needs to authenticate against a third party, explaining the need to authorize the Chromoting app to access the authentication URL." name="IDS_DESCRIPTION_THIRD_PARTY_AUTH"> The remote host requires you to authenticate to a third-party website. To continue, you must grant Chromoting additional permissions to access this address: </message> @@ -394,21 +380,12 @@ <message desc="Error displayed if authentication fails. This can be caused by stale credentials, in which logging out of the web-app and retrying can fix the problem." name="IDS_ERROR_AUTHENTICATION_FAILED" formatter_data="android_java"> Authentication failed. Please sign in to Chromoting again. </message> - <message desc="Error displayed if the client plugin are missing or if they could not be loaded." name="IDS_ERROR_BAD_PLUGIN_VERSION"> - Some components required for Chromoting are missing. Please make sure you have installed the latest version and try again. - </message> - <message desc="Error that is shown on the client side when incompatible Chromoting versions are installed on host and client." name="IDS_ERROR_INCOMPATIBLE_PROTOCOL" formatter_data="android_java"> - An incompatible version of Chromoting was detected. Please make sure that you have the latest version of Chrome and Chromoting on both computers and try again. - </message> <message desc="Error displayed when the computer has a policy that only users in a particular domain may use it as a Chromoting host, and a user in a different domain is trying to use it as a Chromoting host." name="IDS_ERROR_INVALID_HOST_DOMAIN"> Policy settings do not permit sharing this computer as a Chromoting host. Contact your system administrator for assistance. </message> <message desc="Error displayed when an operation is attempted that requires a signed-in user, but no-one is currently signed in." name="IDS_ERROR_NOT_AUTHENTICATED"> You are not signed in to Chromoting. Please sign in and try again. </message> - <message desc="Error displayed if the client plugin fails to load." name="IDS_ERROR_MISSING_PLUGIN"> - Some components required for Chromoting are missing. Please make sure you're running the latest version of Chrome and try again. - </message> <message desc="Message displayed when the current computer is accepting remote connections." name="IDS_HOME_DAEMON_ACTIVE_MESSAGE"> You may securely access this computer using Chromoting. </message> @@ -436,6 +413,9 @@ <message desc="The product name. Displayed in various Chrome pages, including the New Tab page, and displayed prominently on the app's main page." name="IDS_PRODUCT_NAME"> Chromoting </message> + <message desc="The product name. Displayed in various Chrome pages, including the New Tab page, and displayed prominently on the app's main page." name="IDS_PRODUCT_NAME_APP_STREAMING"> + Chromium App Streaming + </message> <message desc="Message displayed at the bottom of the client connect dialog if Chromoting is running in the wrong start-up mode." name="IDS_WARNING_NOT_WINDOWED"> NOTE: To ensure that all keyboard shortcuts are available, you can configure Chromoting to ‘Open as window’. </message> @@ -472,7 +452,91 @@ <message name="IDS_MAC_UNINSTALLER_BUNDLE_NAME" desc="The bundle name specified in the property list of Chromoting Host Uninstaller bundle on MacOS."> Chromoting Host Uninstaller </message> - </if> + </if> <!-- not _google_chrome --> + + <message desc="Error that is shown on the client side when incompatible Chrome Remote Desktop versions are installed on host and client." name="IDS_ERROR_INCOMPATIBLE_PROTOCOL" formatter_data="android_java"> + An incompatible protocol version was detected. Please make sure that you have the latest version of the software installed on both computers and try again. + </message> + <message desc="Text shown when the app first starts, or if the access token is invalidated, explaining the need to authorize the Chromoting app before use." name="IDS_DESCRIPTION_AUTHORIZE"> + To continue you must first grant extended access permissions to your computer. You only have to do this once. + </message> + <message desc="Error displayed if the client plugin are missing or if they could not be loaded." name="IDS_ERROR_BAD_PLUGIN_VERSION"> + Some required components are missing. Please make sure you have installed the latest version of the software and try again. + </message> + <message desc="Error displayed if the client plugin fails to load." name="IDS_ERROR_MISSING_PLUGIN"> + Some required components are missing. Please make sure you're running the latest version of Chrome and try again. + </message> + <message desc="Message shown if the user is not authorized to perform the requested action." name="IDS_ERROR_NOT_AUTHORIZED"> + You do not have permission to perform that action. + </message> + + <!-- The following strings are AppRemoting-specific --> + <message desc="Message shown if the user is not authorized to run the app." name="IDS_ERROR_APP_NOT_AUTHORIZED"> + You do not have permission to run this application. + </message> + <message desc="Menu option to toggle the debugging stats." name="IDS_SHOW_STATS"> + Show statistics + </message> + <message desc="Menu option to toggle the debugging stats, including a summary of the current connection quality." name="IDS_SHOW_STATS_WITH_RTT"> + Show statistics (connection: <ph name="QUALITY">$1<ex>Good</ex></ph>) + </message> + <message desc="Indicates a 'good' quality connection." name="IDS_CONNECTION_QUALITY_GOOD"> + Good + </message> + <message desc="Indicates a 'fair' quality connection." name="IDS_CONNECTION_QUALITY_FAIR"> + Fair + </message> + <message desc="Indicates a 'poor' quality connection." name="IDS_CONNECTION_QUALITY_POOR"> + Poor + </message> + <message desc="Menu option to submit feedback about the product." name="IDS_SEND_FEEDBACK"> + Report an issue… + </message> + <message desc="Title for the dialog prompting the user to consent to their email address being included as part of their feedback." name="IDS_FEEDBACK_CONSENT_TITLE"> + Report an issue + </message> + <message desc="Text asking the user for consent to their email address being included as part of their feedback." name="IDS_FEEDBACK_CONSENT"> + To allow us to contact you for further information, your email address will be included in any feedback you submit. + </message> + <message desc="Title for the submenu item containing a list of windows opened by the remote app." name="IDS_WINDOWS_SUBMENU_TITLE"> + Windows + </message> + <message desc="Checkbox allowing the user to request that their virtual machine be rebooted if it becomes unconnectable." name="IDS_FEEDBACK_ABANDON_HOST"> + Reset the application. You will lose any unsaved work. + </message> + <message desc="Checkbox allowing the user to request that logs be included in their feedback." name="IDS_FEEDBACK_INCLUDE_LOGS"> + Include application logs to help us resolve your problem (logs may include private information). + </message> + <message desc="Link allowing the user to get additional information." name="IDS_LEARN_MORE"> + Learn more. + </message> + <message desc="Detailed privacy information for the feedback feature." name="IDS_FEEDBACK_PRIVACY_INFORMATION1"> + Application logs may include private information, including your identity (email address) and the names and properties of files and folders in Google Drive. + </message> + <message desc="Detailed privacy information for the feedback feature." name="IDS_FEEDBACK_PRIVACY_INFORMATION2"> + This information is used only for diagnosing the problem you are reporting, is available only to someone investigating your report, and is retained for no more than 30 days. + </message> + <message desc="Error message displayed if the reset attempt fails." name="IDS_FEEDBACK_ABANDON_FAILED"> + Could not reset the application. You can still send a bug report. + </message> + <message desc="Title for the submenu item containing a list of windows opened by the remote app." name="IDS_KEYBOARD_LAYOUTS_SUBMENU_TITLE"> + Keyboard layouts + </message> + <message desc="Title for the connection error dialog." name="IDS_CONNECTION_FAILED"> + Connection failed + </message> + <message desc="Warning shown if the platform does not support transparency." name="IDS_NO_TRANSPARENCY_WARNING"> + Desktop integration is not supported on this platform. You can still use the application, but the user experience will be degraded. + </message> + <message desc="Message shown if the user has been idle for a long time, informing them that their session will be disconnected shortly." name="IDS_IDLE_TIMEOUT_WARNING"> + Your <ph name="APPLICATION_NAME">$1<ex>SampleApp Streaming</ex></ph> session has been inactive for a while and will be disconnected shortly. + </message> + <message desc="Button to allow the user to indicate that they are still using the service" name="IDS_IDLE_CONTINUE"> + Continue + </message> + <message desc="Button to allow the user to indicate that they are no longer using the service." name="IDS_IDLE_DISCONNECT"> + Disconnect now + </message> <if expr="is_android or is_ios"> <message desc="Button to show or hide the on-screen keyboard." name="IDS_SHOW_HIDE_KEYBOARD" formatter_data="android_java"> @@ -546,7 +610,7 @@ <message name="IDS_PLAY_STORE_CHANGES" desc="List of what's changed in this release of Chrome Remote Desktop for Android. [CHAR-LIMIT=500] [NAME=play_store_changes]"> • Fixes for Android Lollipop. </message> - </if> + </if> <!-- is_android or is_ios --> <if expr="is_ios"> <message desc="Initial screen's title, welcoming the user." name="IDS_WELCOME"> @@ -567,7 +631,7 @@ <message desc="Menu item to select the Trackpad input mode. In this mode, the mouse cursor is visible and the screen acts as a laptop's trackpad." name ="IDS_SELECT_TRACKPAD_MODE"> Trackpad mode </message> - </if> + </if> <!-- is_ios --> <message desc="Label for the access code entry box. This is where the client user enters the code that permits access to the host." name="IDS_ACCESS_CODE"> Access code @@ -743,8 +807,8 @@ <message desc="Description of the 'share' or 'host' functionality, displayed next to a button that instigates a share operation." name="IDS_HOME_SHARE_DESCRIPTION"> Share this computer for another user to see and control. </message> - <message desc="Text displayed below the description of the 'share' or 'host' functionality on ChromeOS devices, where it is not yet supported." name="IDS_HOME_SHARE_DESCRIPTION_CHROME_OS"> - (this feature is not yet available for Chromebooks… stay tuned) + <message desc="Text displayed below the description of the 'share' or 'host' functionality on an unsupported platform." name="IDS_HOME_SHARE_DESCRIPTION_UNSUPPORTED"> + (this feature is not yet available for your computer) </message> <message desc="In the connection history dialog, clicking this button shows only recent connections to this computer." name="IDS_INCOMING_CONNECTIONS"> To this computer @@ -899,6 +963,9 @@ <message name="IDS_REMOTING_REMOTE_ASSISTANCE_HOST_DESCRIPTION" desc="The file description specified in the version information of remote_assistance_host.exe."> Native messaging host for remote assistance </message> + <message name="IDS_REMOTING_HOST_COMMAND_DESCRIPTION" desc="The file description specified in the version information of remoting_host_command.exe."> + Application to issue commands to Chrome remote desktop host. + </message> <message name="IDS_VERIFY_PIN_DIALOG_EMAIL_LABEL" desc="The message displayed by the PIN verification dialog."> Account </message> @@ -920,6 +987,9 @@ <message name="IDS_HOST_STARTED" desc="The message reported to the EventLog by Chromoting Host every time it is started."> Host started for user: <ph name="HOST_USERNAME">%1<ex>host@email.com</ex></ph>. </message> + <message name="IDS_HOST_STOPPED" desc="The message reported to the EventLog by Chromoting Host every time it is stopped."> + Host stopped. + </message> <message desc="Link to allow a host's paired clients to be viewed or edited." name="IDS_HOME_DAEMON_MANAGE_PAIRINGS"> View/edit </message> @@ -980,6 +1050,7 @@ <message desc="Label for the button to decline sharing the computer in 'It2Me' mode." name="IDS_SHARE_CONFIRM_DIALOG_DECLINE" > Cancel </message> + </messages> </release> </grit>
diff --git a/remoting/webapp/app_remoting/html/template_lg.html b/remoting/webapp/app_remoting/html/template_lg.html index b6827e1..9b666acfa 100644 --- a/remoting/webapp/app_remoting/html/template_lg.html +++ b/remoting/webapp/app_remoting/html/template_lg.html
@@ -17,7 +17,7 @@ <meta-include type="javascript"/> - <title i18n-content="PRODUCT_NAME"></title> + <title i18n-content="PRODUCT_NAME_APP_STREAMING"></title> </head> <body class="full-height">
diff --git a/remoting/webapp/app_remoting/js/app_remoting.js b/remoting/webapp/app_remoting/js/app_remoting.js index 626cbf4b..496eefc 100644 --- a/remoting/webapp/app_remoting/js/app_remoting.js +++ b/remoting/webapp/app_remoting/js/app_remoting.js
@@ -173,7 +173,7 @@ } else if (xhr.status == 401) { that.handleError(remoting.Error.AUTHENTICATION_FAILED); } else if (xhr.status == 403) { - that.handleError(remoting.Error.NOT_AUTHORIZED); + that.handleError(remoting.Error.APP_NOT_AUTHORIZED); } else if (xhr.status == 502 || xhr.status == 503) { that.handleError(remoting.Error.SERVICE_UNAVAILABLE); } else { @@ -343,7 +343,7 @@ console.error('Connection failed: ' + errorTag); remoting.LoadingWindow.close(); remoting.MessageWindow.showErrorMessage( - chrome.i18n.getMessage(/**i18n-content*/'CONNECTION_FAILED'), + chrome.i18n.getMessage(/*i18n-content*/'CONNECTION_FAILED'), chrome.i18n.getMessage(/** @type {string} */ (errorTag))); };
diff --git a/remoting/webapp/app_remoting/js/loading_window.js b/remoting/webapp/app_remoting/js/loading_window.js index e7f8d55..98a710e9 100644 --- a/remoting/webapp/app_remoting/js/loading_window.js +++ b/remoting/webapp/app_remoting/js/loading_window.js
@@ -25,7 +25,7 @@ */ remoting.LoadingWindow.onTimeout_ = function() { remoting.MessageWindow.showErrorMessage( - chrome.i18n.getMessage(/**i18n-content*/'PRODUCT_NAME'), + chrome.i18n.getMessage(/*i18n-content*/'PRODUCT_NAME_APP_STREAMING'), chrome.i18n.getMessage(remoting.Error.SERVICE_UNAVAILABLE)); }; @@ -45,13 +45,13 @@ var transparencyWarning = ''; if (navigator.platform.indexOf('Mac') != -1) { transparencyWarning = - chrome.i18n.getMessage(/**i18n-content*/'NO_TRANSPARENCY_WARNING'); + chrome.i18n.getMessage(/*i18n-content*/'NO_TRANSPARENCY_WARNING'); } remoting.loadingWindow_ = remoting.MessageWindow.showTimedMessageWindow( - chrome.i18n.getMessage(/**i18n-content*/'PRODUCT_NAME'), - chrome.i18n.getMessage(/**i18n-content*/'FOOTER_CONNECTING'), + chrome.i18n.getMessage(/*i18n-content*/'PRODUCT_NAME_APP_STREAMING'), + chrome.i18n.getMessage(/*i18n-content*/'FOOTER_CONNECTING'), transparencyWarning, - chrome.i18n.getMessage(/**i18n-content*/'CANCEL'), + chrome.i18n.getMessage(/*i18n-content*/'CANCEL'), remoting.MessageWindow.quitApp, kConnectionTimeout, remoting.LoadingWindow.onTimeout_);
diff --git a/remoting/webapp/base/js/message_window_helper.js b/remoting/webapp/base/js/message_window_helper.js index 88303f5..030244a 100644 --- a/remoting/webapp/base/js/message_window_helper.js +++ b/remoting/webapp/base/js/message_window_helper.js
@@ -251,7 +251,7 @@ var options = /** @type {remoting.MessageWindowOptions} */ ({ title: title, message: message, - buttonLabel: chrome.i18n.getMessage(/**i18n-content*/'OK'), + buttonLabel: chrome.i18n.getMessage(/*i18n-content*/'OK'), onResult: remoting.MessageWindow.quitApp }); return new remoting.MessageWindow(options);
diff --git a/remoting/webapp/crd/html/ui_it2me.html b/remoting/webapp/crd/html/ui_it2me.html index 15a3b10..47b5041 100644 --- a/remoting/webapp/crd/html/ui_it2me.html +++ b/remoting/webapp/crd/html/ui_it2me.html
@@ -28,8 +28,8 @@ <div class="section-row"> <div class="box-spacer"> <div i18n-content="HOME_SHARE_DESCRIPTION"></div> - <div id="chrome-os-no-share" - i18n-content="HOME_SHARE_DESCRIPTION_CHROME_OS" + <div id="unsupported-platform-message" + i18n-content="HOME_SHARE_DESCRIPTION_UNSUPPORTED" class="small-print"></div> </div> <div>
diff --git a/remoting/webapp/crd/js/client_plugin_impl.js b/remoting/webapp/crd/js/client_plugin_impl.js index 17b4adf..af0fc723 100644 --- a/remoting/webapp/crd/js/client_plugin_impl.js +++ b/remoting/webapp/crd/js/client_plugin_impl.js
@@ -648,6 +648,12 @@ } else if (remoting.platformIsChromeOS()) { keyFilter = 'cros'; } + // Use PPB_VideoDecoder API only in Chrome 42 and above. It is broken in + // previous versions of Chrome, see http://crbug.com/447403 . + // Currently PPAPI doesn't provide a way for plugins to check the Chrome + // version, so this check needs to be in the webapp. + var enableVideoDecodeRenderer = + parseInt((remoting.getChromeVersion() || '0').split('.')[0], 10) >= 42; this.plugin_.postMessage(JSON.stringify( { method: 'delegateLargeCursors', data: {} })); this.plugin_.postMessage(JSON.stringify( @@ -661,7 +667,8 @@ capabilities: this.capabilities_.join(" "), clientPairingId: clientPairingId, clientPairedSecret: clientPairedSecret, - keyFilter: keyFilter + keyFilter: keyFilter, + enableVideoDecodeRenderer: enableVideoDecodeRenderer } })); };
diff --git a/remoting/webapp/crd/js/client_session.js b/remoting/webapp/crd/js/client_session.js index 8c54cb74..f0fa9b4 100644 --- a/remoting/webapp/crd/js/client_session.js +++ b/remoting/webapp/crd/js/client_session.js
@@ -408,10 +408,6 @@ // Indicates that the client supports 'cast'ing the video stream to a // cast-enabled device. CAST: 'casting', - - // When enabled, this capability results in the client informing the host - // that it supports Gnubby-based authentication. - GNUBBY_AUTH: 'gnubbyAuth' }; /** @@ -1572,8 +1568,7 @@ * @private */ remoting.ClientSession.prototype.createGnubbyAuthHandler_ = function() { - if (this.hasCapability_(remoting.ClientSession.Capability.GNUBBY_AUTH) && - this.mode_ == remoting.ClientSession.Mode.ME2ME) { + if (this.mode_ == remoting.ClientSession.Mode.ME2ME) { this.gnubbyAuthHandler_ = new remoting.GnubbyAuthHandler(this); // TODO(psj): Move to more generic capabilities mechanism. this.sendGnubbyAuthMessage({'type': 'control', 'option': 'auth-v1'});
diff --git a/remoting/webapp/crd/js/crd_main.js b/remoting/webapp/crd/js/crd_main.js index 9b57b233..f772320 100644 --- a/remoting/webapp/crd/js/crd_main.js +++ b/remoting/webapp/crd/js/crd_main.js
@@ -19,16 +19,16 @@ document.getElementById('host-list-loading-indicator')); isHostModeSupported_().then( - /** @param {Boolean} supported */ - function(supported){ - if (supported) { - var noShare = document.getElementById('chrome-os-no-share'); - noShare.parentNode.removeChild(noShare); - } else { - var button = document.getElementById('share-button'); - button.disabled = true; - } - }); + /** @param {Boolean} supported */ + function(supported) { + if (supported) { + var noShare = document.getElementById('unsupported-platform-message'); + noShare.parentNode.removeChild(noShare); + } else { + var button = document.getElementById('share-button'); + button.disabled = true; + } + }); /** * @return {Promise} A promise that resolves to the id of the current @@ -87,20 +87,16 @@ } /** - * Returns whether Host mode is supported on this platform for It2me. - * TODO(kelvinp): Remove this function once It2me is enabled on Chrome OS (See - * crbug.com/429860). + * Returns whether Host mode is supported on this platform for It2Me. * * @return {Promise} Resolves to true if Host mode is supported. */ function isHostModeSupported_() { - if (!remoting.platformIsChromeOS()) { + if (remoting.HostInstaller.canInstall()) { return Promise.resolve(true); } - // Sharing on Chrome OS is currently behind a flag. - // isInstalled() will return false if the flag is disabled. - var hostInstaller = new remoting.HostInstaller(); - return hostInstaller.isInstalled(); + + return remoting.HostInstaller.isInstalled(); } /**
diff --git a/remoting/webapp/crd/js/desktop_remoting.js b/remoting/webapp/crd/js/desktop_remoting.js index ab26626..ad9f0b6 100644 --- a/remoting/webapp/crd/js/desktop_remoting.js +++ b/remoting/webapp/crd/js/desktop_remoting.js
@@ -138,8 +138,7 @@ remoting.ClientSession.Capability.VIDEO_RECORDER, // TODO(aiguha): Add this capability based on a gyp/command-line flag, // rather than by default. - remoting.ClientSession.Capability.CAST, - remoting.ClientSession.Capability.GNUBBY_AUTH + remoting.ClientSession.Capability.CAST ]; };
diff --git a/remoting/webapp/crd/js/error.js b/remoting/webapp/crd/js/error.js index 137372f..3001f9a9 100644 --- a/remoting/webapp/crd/js/error.js +++ b/remoting/webapp/crd/js/error.js
@@ -32,7 +32,10 @@ INVALID_HOST_DOMAIN: /*i18n-content*/'ERROR_INVALID_HOST_DOMAIN', P2P_FAILURE: /*i18n-content*/'ERROR_P2P_FAILURE', REGISTRATION_FAILED: /*i18n-content*/'ERROR_HOST_REGISTRATION_FAILED', - NOT_AUTHORIZED: /*i18n-content*/'ERROR_NOT_AUTHORIZED' + NOT_AUTHORIZED: /*i18n-content*/'ERROR_NOT_AUTHORIZED', + + // TODO(garykac): Move app-specific errors into separate location. + APP_NOT_AUTHORIZED: /*i18n-content*/'ERROR_APP_NOT_AUTHORIZED' }; /**
diff --git a/remoting/webapp/crd/js/fullscreen_v2.js b/remoting/webapp/crd/js/fullscreen_v2.js index ea20f900..b07931b 100644 --- a/remoting/webapp/crd/js/fullscreen_v2.js +++ b/remoting/webapp/crd/js/fullscreen_v2.js
@@ -18,16 +18,24 @@ */ remoting.FullscreenAppsV2 = function() { /** - * @type {boolean} True if the next onRestored event should cause callbacks - * to be notified of a full-screen changed event. onRestored fires when - * full-screen mode is exited and also when the window is restored from - * being minimized; callbacks should not be notified of the latter. + * @type {boolean} True if the window is minimized. onRestored fires when the + * the window transitions from minimized to any other state, but since we + * only want transitions from full-screen to windowed to cause a callback, + * we must keep track of the minimized state of the window. * @private */ - this.notifyCallbacksOnRestore_ = this.isActive(); + this.isMinimized_ = chrome.app.window.current().isMinimized(); /** - * @type {string} Internal 'full-screen changed' event name + * @type {?boolean} The most recent full-screen state passed to the callback. + * This guards against redundant invocations, as as would otherwise occur + * in response to a full-screen -> maximized -> unmaximized transition, + * because this results in two onRestored callbacks. + */ + this.previousCallbackState_ = null; + + /** + * @type {string} Internal 'full-screen changed' event name. * @private */ this.kEventName_ = '_fullscreenchanged'; @@ -43,8 +51,14 @@ this.onFullscreened_.bind(this)); chrome.app.window.current().onRestored.addListener( this.onRestored_.bind(this)); + chrome.app.window.current().onMinimized.addListener( + this.onMinimized_.bind(this)); }; +/** + * @param {boolean} fullscreen True to enter full-screen mode; false to leave. + * @param {function():void=} opt_onDone Optional completion callback. + */ remoting.FullscreenAppsV2.prototype.activate = function( fullscreen, opt_onDone) { if (opt_onDone) { @@ -72,6 +86,9 @@ this.activate(!this.isActive()); }; +/** + * @return {boolean} + */ remoting.FullscreenAppsV2.prototype.isActive = function() { return chrome.app.window.current().isFullscreen(); }; @@ -90,16 +107,40 @@ this.eventSource_.removeEventListener(this.kEventName_, callback); }; +/** + * @private + */ remoting.FullscreenAppsV2.prototype.onFullscreened_ = function() { - this.notifyCallbacksOnRestore_ = true; - this.eventSource_.raiseEvent(this.kEventName_, true); + this.isMinimized_ = false; + this.raiseEvent_(true); document.body.classList.add('fullscreen'); }; +/** + * @private + */ remoting.FullscreenAppsV2.prototype.onRestored_ = function() { - document.body.classList.remove('fullscreen'); - if (this.notifyCallbacksOnRestore_) { - this.notifyCallbacksOnRestore_ = false; - this.eventSource_.raiseEvent(this.kEventName_, false); + if (!this.isMinimized_) { + document.body.classList.remove('fullscreen'); + this.raiseEvent_(false); + } + this.isMinimized_ = false; +}; + +/** + * @private + */ +remoting.FullscreenAppsV2.prototype.onMinimized_ = function() { + this.isMinimized_ = true; +}; + +/** + * @param {boolean} isFullscreen + * @private + */ +remoting.FullscreenAppsV2.prototype.raiseEvent_ = function(isFullscreen) { + if (isFullscreen !== this.previousCallbackState_) { + this.previousCallbackState_ = isFullscreen; + this.eventSource_.raiseEvent(this.kEventName_, isFullscreen); } };
diff --git a/remoting/webapp/crd/js/host_installer.js b/remoting/webapp/crd/js/host_installer.js index 8ae9b36b..6f1f310 100644 --- a/remoting/webapp/crd/js/host_installer.js +++ b/remoting/webapp/crd/js/host_installer.js
@@ -26,6 +26,8 @@ /** @suppress {duplicate} */ var remoting = remoting || {}; +(function() { + /** * @constructor */ @@ -47,7 +49,7 @@ * @return {Promise} The promise will resolve to a boolean value indicating * whether the host is installed or not. */ -remoting.HostInstaller.prototype.isInstalled = function() { +remoting.HostInstaller.isInstalled = function() { // Always do a fresh check as we don't get notified when the host is // uninstalled. @@ -78,28 +80,39 @@ }); }; +/** @type {Object.<string,string>} */ +var HOST_DOWNLOAD_URLS = { + 'Win32': 'http://dl.google.com/dl/edgedl/chrome-remote-desktop/' + + 'chromeremotedesktophost.msi', + 'Win64': 'http://dl.google.com/dl/edgedl/chrome-remote-desktop/' + + 'chromeremotedesktophost.msi', + 'MacIntel': 'https://dl.google.com/chrome-remote-desktop/' + + 'chromeremotedesktop.dmg', + 'Linux x86_64': 'https://dl.google.com/linux/direct/' + + 'chrome-remote-desktop_current_amd64.deb', + 'Linux i386': 'https://dl.google.com/linux/direct/' + + 'chrome-remote-desktop_current_i386.deb', + 'Linux i686': 'https://dl.google.com/linux/direct/' + + 'chrome-remote-desktop_current_i386.deb' +}; + +/** + * Returns true if the host is installable on the current platform. + * @returns {boolean} + */ +remoting.HostInstaller.canInstall = function() { + return !!HOST_DOWNLOAD_URLS[navigator.platform]; +}; + /** * @throws {Error} Throws if there is no matching host binary for the current * platform. */ remoting.HostInstaller.prototype.download = function() { - /** @type {Object.<string,string>} */ - var hostDownloadUrls = { - 'Win32' : 'http://dl.google.com/dl/edgedl/chrome-remote-desktop/' + - 'chromeremotedesktophost.msi', - 'Win64' : 'http://dl.google.com/dl/edgedl/chrome-remote-desktop/' + - 'chromeremotedesktophost.msi', - 'MacIntel' : 'https://dl.google.com/chrome-remote-desktop/' + - 'chromeremotedesktop.dmg', - 'Linux x86_64' : 'https://dl.google.com/linux/direct/' + - 'chrome-remote-desktop_current_amd64.deb', - 'Linux i386' : 'https://dl.google.com/linux/direct/' + - 'chrome-remote-desktop_current_i386.deb' - }; - - var hostPackageUrl = hostDownloadUrls[navigator.platform]; + var hostPackageUrl = HOST_DOWNLOAD_URLS[navigator.platform]; if (hostPackageUrl === undefined) { - throw new Error(remoting.Error.CANCELLED); + console.error("Tried to install host on " + navigator.platform); + throw new Error(remoting.Error.UNEXPECTED); } // Start downloading the package. @@ -122,7 +135,7 @@ */ var CHECK_INSTALL_INTERVAL_IN_MILLISECONDS = 1000; - return this.isInstalled().then( + return remoting.HostInstaller.isInstalled().then( /** @param {boolean} installed */ function(installed){ if (installed) { @@ -135,7 +148,7 @@ function(resolve){ that.download(); that.checkInstallIntervalId_ = window.setInterval(function() { - that.isInstalled().then( + remoting.HostInstaller.isInstalled().then( /** @param {boolean} installed */ function(installed) { if (installed) { @@ -163,3 +176,5 @@ } this.downloadAndWaitForInstallPromise_ = null; }; + +})();
diff --git a/remoting/webapp/crd/js/identity.js b/remoting/webapp/crd/js/identity.js index 63e70d47..aef0f2c 100644 --- a/remoting/webapp/crd/js/identity.js +++ b/remoting/webapp/crd/js/identity.js
@@ -29,10 +29,10 @@ remoting.Identity = function(consentCallback) { /** @private */ this.consentCallback_ = consentCallback; - /** @type {?string} @private */ - this.email_ = null; - /** @type {?string} @private */ - this.fullName_ = null; + /** @type {string} @private */ + this.email_ = ''; + /** @type {string} @private */ + this.fullName_ = ''; /** @type {Array.<remoting.Identity.Callbacks>} */ this.pendingCallbacks_ = []; }; @@ -110,8 +110,14 @@ * @return {void} Nothing. */ remoting.Identity.prototype.getUserInfo = function(onOk, onError) { + if (this.isAuthenticated()) { + onOk(this.email_, this.fullName_); + return; + } + /** @type {remoting.Identity} */ var that = this; + /** * @param {string} email * @param {string} name @@ -129,6 +135,21 @@ }; /** + * Get the user's email address. + * + * @param {function(string):void} onOk Callback invoked when the email + * address is available. + * @param {function(remoting.Error):void} onError Callback invoked if an + * error occurs. + * @return {void} Nothing. + */ +remoting.Identity.prototype.getEmail = function(onOk, onError) { + this.getUserInfo(function(email, name) { + onOk(email); + }, onError); +}; + +/** * Get the user's email address, or null if no successful call to getUserInfo * has been made. * @@ -221,5 +242,5 @@ * @return {boolean} */ remoting.Identity.prototype.isAuthenticated = function() { - return remoting.identity.email_ != null; + return remoting.identity.email_ !== ''; };
diff --git a/remoting/webapp/crd/js/it2me_helpee_channel.js b/remoting/webapp/crd/js/it2me_helpee_channel.js index eedb663..e4060ac 100644 --- a/remoting/webapp/crd/js/it2me_helpee_channel.js +++ b/remoting/webapp/crd/js/it2me_helpee_channel.js
@@ -214,7 +214,7 @@ }); } - this.hostInstaller_.isInstalled().then( + remoting.HostInstaller.isInstalled().then( sendResponse, /** @type {function(*):void} */(this.sendErrorResponse_.bind(this, message)) );
diff --git a/remoting/webapp/crd/js/xmpp_connection.js b/remoting/webapp/crd/js/xmpp_connection.js index 34d7a7d..18e69ac 100644 --- a/remoting/webapp/crd/js/xmpp_connection.js +++ b/remoting/webapp/crd/js/xmpp_connection.js
@@ -325,7 +325,8 @@ this.streamParser_.appendData(readInfo.data); } - if (!this.startTlsPending_) { + if (!this.startTlsPending_ && + this.state_ != remoting.SignalStrategy.State.CLOSED) { this.tryRead_(); } };
diff --git a/remoting/webapp/js_proto/chrome_proto.js b/remoting/webapp/js_proto/chrome_proto.js index 9f792bd..c7de1ac 100644 --- a/remoting/webapp/js_proto/chrome_proto.js +++ b/remoting/webapp/js_proto/chrome_proto.js
@@ -366,6 +366,8 @@ /** @type {chrome.Event} */ this.onMaximized = null; /** @type {chrome.Event} */ + this.onMinimized = null; + /** @type {chrome.Event} */ this.onFullscreened = null; /** @type {string} */ this.id = '';
diff --git a/remoting/webapp/unittests/it2me_helpee_channel_unittest.js b/remoting/webapp/unittests/it2me_helpee_channel_unittest.js index 504affc..4ccfb08 100644 --- a/remoting/webapp/unittests/it2me_helpee_channel_unittest.js +++ b/remoting/webapp/unittests/it2me_helpee_channel_unittest.js
@@ -34,7 +34,6 @@ // HostInstaller hostInstaller = { - isInstalled: function() {}, download: function() {} }; @@ -64,7 +63,8 @@ QUnit.asyncTest( 'isHostInstalled() should return false if host is not installed', function() { - sinon.stub(hostInstaller, 'isInstalled').returns(Promise.resolve(false)); + sinon.stub(remoting.HostInstaller, 'isInstalled') + .returns(Promise.resolve(false)); var MessageTypes = remoting.It2MeHelpeeChannel.HangoutMessageTypes; hangoutPort.onMessage.mock$fire({ @@ -72,6 +72,7 @@ }); window.requestAnimationFrame(function() { + remoting.HostInstaller.isInstalled.restore(); sinon.assert.calledWith(hangoutPort.postMessage, { method: MessageTypes.IS_HOST_INSTALLED_RESPONSE, result: false @@ -82,7 +83,8 @@ QUnit.asyncTest('isHostInstalled() should return true if host is installed', function() { - sinon.stub(hostInstaller, 'isInstalled').returns(Promise.resolve(true)); + sinon.stub(remoting.HostInstaller, 'isInstalled') + .returns(Promise.resolve(true)); var MessageTypes = remoting.It2MeHelpeeChannel.HangoutMessageTypes; hangoutPort.onMessage.mock$fire({ @@ -90,6 +92,7 @@ }); window.requestAnimationFrame(function() { + remoting.HostInstaller.isInstalled.restore(); sinon.assert.calledWith(hangoutPort.postMessage, { method: MessageTypes.IS_HOST_INSTALLED_RESPONSE, result: true
diff --git a/rlz/chromeos/lib/rlz_value_store_chromeos.h b/rlz/chromeos/lib/rlz_value_store_chromeos.h index 391e22b..9f92549 100644 --- a/rlz/chromeos/lib/rlz_value_store_chromeos.h +++ b/rlz/chromeos/lib/rlz_value_store_chromeos.h
@@ -28,36 +28,33 @@ // Creates new instance and synchronously reads data from file. RlzValueStoreChromeOS(const base::FilePath& store_path); - virtual ~RlzValueStoreChromeOS(); + ~RlzValueStoreChromeOS() override; // RlzValueStore overrides: - virtual bool HasAccess(AccessType type) override; + bool HasAccess(AccessType type) override; - virtual bool WritePingTime(Product product, int64 time) override; - virtual bool ReadPingTime(Product product, int64* time) override; - virtual bool ClearPingTime(Product product) override; + bool WritePingTime(Product product, int64 time) override; + bool ReadPingTime(Product product, int64* time) override; + bool ClearPingTime(Product product) override; - virtual bool WriteAccessPointRlz(AccessPoint access_point, - const char* new_rlz) override; - virtual bool ReadAccessPointRlz(AccessPoint access_point, - char* rlz, - size_t rlz_size) override; - virtual bool ClearAccessPointRlz(AccessPoint access_point) override; + bool WriteAccessPointRlz(AccessPoint access_point, + const char* new_rlz) override; + bool ReadAccessPointRlz(AccessPoint access_point, + char* rlz, + size_t rlz_size) override; + bool ClearAccessPointRlz(AccessPoint access_point) override; - virtual bool AddProductEvent(Product product, const char* event_rlz) override; - virtual bool ReadProductEvents(Product product, - std::vector<std::string>* events) override; - virtual bool ClearProductEvent(Product product, - const char* event_rlz) override; - virtual bool ClearAllProductEvents(Product product) override; + bool AddProductEvent(Product product, const char* event_rlz) override; + bool ReadProductEvents(Product product, + std::vector<std::string>* events) override; + bool ClearProductEvent(Product product, const char* event_rlz) override; + bool ClearAllProductEvents(Product product) override; - virtual bool AddStatefulEvent(Product product, - const char* event_rlz) override; - virtual bool IsStatefulEvent(Product product, - const char* event_rlz) override; - virtual bool ClearAllStatefulEvents(Product product) override; + bool AddStatefulEvent(Product product, const char* event_rlz) override; + bool IsStatefulEvent(Product product, const char* event_rlz) override; + bool ClearAllStatefulEvents(Product product) override; - virtual void CollectGarbage() override; + void CollectGarbage() override; private: // Reads RLZ store from file.
diff --git a/sandbox/linux/BUILD.gn b/sandbox/linux/BUILD.gn index b5cfcdb9..120b4b7 100644 --- a/sandbox/linux/BUILD.gn +++ b/sandbox/linux/BUILD.gn
@@ -114,6 +114,7 @@ if (compile_credentials) { sources += [ "services/credentials_unittest.cc", + "services/namespace_utils_unittest.cc", "services/proc_util_unittest.cc", "services/unix_domain_socket_unittest.cc", ] @@ -254,6 +255,8 @@ sources += [ "services/credentials.cc", "services/credentials.h", + "services/namespace_utils.cc", + "services/namespace_utils.h", "services/proc_util.cc", "services/proc_util.h", ]
diff --git a/sandbox/linux/sandbox_linux.gypi b/sandbox/linux/sandbox_linux.gypi index 89c830e..d5b2608 100644 --- a/sandbox/linux/sandbox_linux.gypi +++ b/sandbox/linux/sandbox_linux.gypi
@@ -254,6 +254,8 @@ 'sources': [ 'services/credentials.cc', 'services/credentials.h', + 'services/namespace_utils.cc', + 'services/namespace_utils.h', 'services/proc_util.cc', 'services/proc_util.h', ],
diff --git a/sandbox/linux/sandbox_linux_test_sources.gypi b/sandbox/linux/sandbox_linux_test_sources.gypi index 5aeacf6..42e9598 100644 --- a/sandbox/linux/sandbox_linux_test_sources.gypi +++ b/sandbox/linux/sandbox_linux_test_sources.gypi
@@ -54,6 +54,7 @@ [ 'compile_credentials==1', { 'sources': [ 'services/credentials_unittest.cc', + 'services/namespace_utils_unittest.cc', 'services/proc_util_unittest.cc', 'services/unix_domain_socket_unittest.cc', ],
diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions_unittests.cc b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions_unittests.cc index 01ad1f2..b76b8e11 100644 --- a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions_unittests.cc +++ b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions_unittests.cc
@@ -92,12 +92,12 @@ public: ClockSystemTesterDelegate() : is_running_on_chromeos_(base::SysInfo::IsRunningOnChromeOS()) {} - virtual ~ClockSystemTesterDelegate() {} + ~ClockSystemTesterDelegate() override {} - virtual scoped_ptr<sandbox::bpf_dsl::Policy> GetSandboxBPFPolicy() override { + scoped_ptr<sandbox::bpf_dsl::Policy> GetSandboxBPFPolicy() override { return scoped_ptr<sandbox::bpf_dsl::Policy>(new RestrictClockIdPolicy()); } - virtual void RunTestFunction() override { + void RunTestFunction() override { if (is_running_on_chromeos_) { CheckClock(base::TimeTicks::kClockSystemTrace); } else {
diff --git a/sandbox/linux/services/credentials.cc b/sandbox/linux/services/credentials.cc index be03e15a..ce5eeda7 100644 --- a/sandbox/linux/services/credentials.cc +++ b/sandbox/linux/services/credentials.cc
@@ -22,6 +22,7 @@ #include "base/process/launch.h" #include "base/template_util.h" #include "base/third_party/valgrind/valgrind.h" +#include "sandbox/linux/services/namespace_utils.h" #include "sandbox/linux/services/syscall_wrappers.h" namespace sandbox { @@ -50,39 +51,6 @@ // Wrapper to manage the result from libcap2's cap_from_text(). typedef scoped_ptr<char, CapTextFreeDeleter> ScopedCapText; -struct FILECloser { - inline void operator()(FILE* f) const { - DCHECK(f); - PCHECK(0 == fclose(f)); - } -}; - -// Don't use ScopedFILE in base since it doesn't check fclose(). -// TODO(jln): fix base/. -typedef scoped_ptr<FILE, FILECloser> ScopedFILE; - -static_assert((base::is_same<uid_t, gid_t>::value), - "uid_t and gid_t should be the same type"); -// generic_id_t can be used for either uid_t or gid_t. -typedef uid_t generic_id_t; - -// Write a uid or gid mapping from |id| to |id| in |map_file|. -bool WriteToIdMapFile(const char* map_file, generic_id_t id) { - ScopedFILE f(fopen(map_file, "w")); - PCHECK(f); - const uid_t inside_id = id; - const uid_t outside_id = id; - int num = fprintf(f.get(), "%d %d 1\n", inside_id, outside_id); - if (num < 0) return false; - // Manually call fflush() to catch permission failures. - int ret = fflush(f.get()); - if (ret) { - VLOG(1) << "Could not write to id map file"; - return false; - } - return true; -} - // Checks that the set of RES-uids and the set of RES-gids have // one element each and return that element in |resuid| and |resgid| // respectively. It's ok to pass NULL as one or both of the ids. @@ -187,7 +155,7 @@ } // static -bool Credentials::SupportsNewUserNS() { +bool Credentials::CanCreateProcessInNewUserNS() { // Valgrind will let clone(2) pass-through, but doesn't support unshare(), // so always consider UserNS unsupported there. if (IsRunningOnValgrind()) { @@ -240,8 +208,8 @@ DCHECK(GetRESIds(NULL, NULL)); const char kGidMapFile[] = "/proc/self/gid_map"; const char kUidMapFile[] = "/proc/self/uid_map"; - CHECK(WriteToIdMapFile(kGidMapFile, gid)); - CHECK(WriteToIdMapFile(kUidMapFile, uid)); + CHECK(NamespaceUtils::WriteToIdMapFile(kGidMapFile, gid)); + CHECK(NamespaceUtils::WriteToIdMapFile(kUidMapFile, uid)); DCHECK(GetRESIds(NULL, NULL)); return true; }
diff --git a/sandbox/linux/services/credentials.h b/sandbox/linux/services/credentials.h index fc65afc..a526176 100644 --- a/sandbox/linux/services/credentials.h +++ b/sandbox/linux/services/credentials.h
@@ -39,9 +39,9 @@ // Returns whether the kernel supports CLONE_NEWUSER and whether it would be // possible to immediately move to a new user namespace. There is no point // in using this method right before calling MoveToNewUserNS(), simply call - // MoveToNewUserNS() immediately. This method is only useful to test kernel - // support ahead of time. - static bool SupportsNewUserNS(); + // MoveToNewUserNS() immediately. This method is only useful to test the + // ability to move to a user namespace ahead of time. + static bool CanCreateProcessInNewUserNS(); // Move the current process to a new "user namespace" as supported by Linux // 3.8+ (CLONE_NEWUSER).
diff --git a/sandbox/linux/services/credentials_unittest.cc b/sandbox/linux/services/credentials_unittest.cc index 8b41917..eb0ff83 100644 --- a/sandbox/linux/services/credentials_unittest.cc +++ b/sandbox/linux/services/credentials_unittest.cc
@@ -71,9 +71,9 @@ CHECK(!Credentials::HasAnyCapability()); } -SANDBOX_TEST(Credentials, SupportsUserNS) { +SANDBOX_TEST(Credentials, CanCreateProcessInNewUserNS) { CHECK(Credentials::DropAllCapabilities()); - bool user_ns_supported = Credentials::SupportsNewUserNS(); + bool user_ns_supported = Credentials::CanCreateProcessInNewUserNS(); bool moved_to_new_ns = Credentials::MoveToNewUserNS(); CHECK_EQ(user_ns_supported, moved_to_new_ns); } @@ -154,7 +154,7 @@ // The kernel should now prevent us from regaining capabilities because we // are in a chroot. - CHECK(!Credentials::SupportsNewUserNS()); + CHECK(!Credentials::CanCreateProcessInNewUserNS()); CHECK(!Credentials::MoveToNewUserNS()); }
diff --git a/sandbox/linux/services/namespace_utils.cc b/sandbox/linux/services/namespace_utils.cc new file mode 100644 index 0000000..f03fe40 --- /dev/null +++ b/sandbox/linux/services/namespace_utils.cc
@@ -0,0 +1,90 @@ +// Copyright 2015 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 "sandbox/linux/services/namespace_utils.h" + +#include <fcntl.h> +#include <sched.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> + +#include <string> + +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/files/scoped_file.h" +#include "base/logging.h" +#include "base/posix/eintr_wrapper.h" +#include "base/process/launch.h" +#include "base/strings/stringprintf.h" +#include "base/third_party/valgrind/valgrind.h" + +namespace sandbox { + +namespace { +bool IsRunningOnValgrind() { + return RUNNING_ON_VALGRIND; +} +} // namespace + +// static +bool NamespaceUtils::WriteToIdMapFile(const char* map_file, generic_id_t id) { + base::ScopedFD fd(HANDLE_EINTR(open(map_file, O_WRONLY))); + if (!fd.is_valid()) { + return false; + } + + const generic_id_t inside_id = id; + const generic_id_t outside_id = id; + const std::string mapping = + base::StringPrintf("%d %d 1\n", inside_id, outside_id); + const size_t len = mapping.size(); + const ssize_t rc = HANDLE_EINTR(write(fd.get(), mapping.c_str(), len)); + return rc == static_cast<ssize_t>(len); +} + +// static +bool NamespaceUtils::KernelSupportsUnprivilegedNamespace(int type) { + // Valgrind will let clone(2) pass-through, but doesn't support unshare(), + // so always consider namespaces unsupported there. + if (IsRunningOnValgrind()) { + return false; + } + + // As of Linux 3.8, /proc/self/ns/* files exist for all namespace types. Since + // user namespaces were added in 3.8, it is OK to rely on the existence of + // /proc/self/ns/*. + if (!base::PathExists(base::FilePath("/proc/self/ns/user"))) { + return false; + } + + const char* path; + switch (type) { + case CLONE_NEWUSER: + return true; + case CLONE_NEWIPC: + path = "/proc/self/ns/ipc"; + break; + case CLONE_NEWNET: + path = "/proc/self/ns/net"; + break; + case CLONE_NEWNS: + path = "/proc/self/ns/mnt"; + break; + case CLONE_NEWPID: + path = "/proc/self/ns/pid"; + break; + case CLONE_NEWUTS: + path = "/proc/self/ns/uts"; + break; + default: + NOTREACHED(); + return false; + } + + return base::PathExists(base::FilePath(path)); +} + +} // namespace sandbox
diff --git a/sandbox/linux/services/namespace_utils.h b/sandbox/linux/services/namespace_utils.h new file mode 100644 index 0000000..d248d95 --- /dev/null +++ b/sandbox/linux/services/namespace_utils.h
@@ -0,0 +1,39 @@ +// Copyright 2015 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 SANDBOX_LINUX_SERVICES_NAMESPACE_UTILS_H_ +#define SANDBOX_LINUX_SERVICES_NAMESPACE_UTILS_H_ + +#include <sys/types.h> + +#include "base/macros.h" +#include "base/template_util.h" +#include "sandbox/sandbox_export.h" + +namespace sandbox { + +// Utility functions for using Linux namepaces. +class SANDBOX_EXPORT NamespaceUtils { + public: + COMPILE_ASSERT((base::is_same<uid_t, gid_t>::value), UidAndGidAreSameType); + // generic_id_t can be used for either uid_t or gid_t. + typedef uid_t generic_id_t; + + // Write a uid or gid mapping from |id| to |id| in |map_file|. + static bool WriteToIdMapFile(const char* map_file, generic_id_t id); + + // Returns true if unprivileged namespaces of type |type| is supported + // (meaning that both CLONE_NEWUSER and type are are supported). |type| must + // be one of CLONE_NEWIPC, CLONE_NEWNET, CLONE_NEWNS, CLONE_NEWPID, + // CLONE_NEWUSER, or CLONE_NEWUTS. This relies on access to /proc, so it will + // not work from within a sandbox. + static bool KernelSupportsUnprivilegedNamespace(int type); + + private: + DISALLOW_IMPLICIT_CONSTRUCTORS(NamespaceUtils); +}; + +} // namespace sandbox + +#endif // SANDBOX_LINUX_SERVICES_NAMESPACE_UTILS_H_
diff --git a/sandbox/linux/services/namespace_utils_unittest.cc b/sandbox/linux/services/namespace_utils_unittest.cc new file mode 100644 index 0000000..33ead94 --- /dev/null +++ b/sandbox/linux/services/namespace_utils_unittest.cc
@@ -0,0 +1,65 @@ +// Copyright 2015 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 "sandbox/linux/services/namespace_utils.h" + +#include <errno.h> +#include <sched.h> +#include <sys/types.h> +#include <sys/wait.h> + +#include "base/logging.h" +#include "base/posix/eintr_wrapper.h" +#include "base/process/launch.h" +#include "sandbox/linux/services/credentials.h" +#include "sandbox/linux/tests/unit_tests.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace sandbox { + +namespace { + +SANDBOX_TEST(NamespaceUtils, KernelSupportsUnprivilegedNamespace) { + const bool can_create_user_ns = Credentials::CanCreateProcessInNewUserNS(); + const bool supports_user_ns = + NamespaceUtils::KernelSupportsUnprivilegedNamespace(CLONE_NEWUSER); + // can_create_user_ns implies supports_user_ns, but the converse is not + // necessarily true, as creating a user namespace can fail for various + // reasons. + if (can_create_user_ns) { + SANDBOX_ASSERT(supports_user_ns); + } +} + +SANDBOX_TEST(NamespaceUtils, WriteToIdMapFile) { + if (!Credentials::CanCreateProcessInNewUserNS()) { + return; + } + + const uid_t uid = getuid(); + const gid_t gid = getgid(); + + const pid_t pid = + base::ForkWithFlags(CLONE_NEWUSER | SIGCHLD, nullptr, nullptr); + ASSERT_NE(-1, pid); + if (pid == 0) { + RAW_CHECK(getuid() != uid); + NamespaceUtils::WriteToIdMapFile("/proc/self/uid_map", uid); + RAW_CHECK(getuid() == uid); + + RAW_CHECK(getgid() != gid); + NamespaceUtils::WriteToIdMapFile("/proc/self/gid_map", gid); + RAW_CHECK(getgid() == gid); + + _exit(0); + } + + int status = 42; + SANDBOX_ASSERT_EQ(pid, HANDLE_EINTR(waitpid(pid, &status, 0))); + SANDBOX_ASSERT_EQ(0, status); +} + +} // namespace. + +} // namespace sandbox.
diff --git a/sandbox/mac/bootstrap_sandbox_unittest.mm b/sandbox/mac/bootstrap_sandbox_unittest.mm index bd788bd2..7e5e8b6 100644 --- a/sandbox/mac/bootstrap_sandbox_unittest.mm +++ b/sandbox/mac/bootstrap_sandbox_unittest.mm
@@ -107,7 +107,7 @@ EXPECT_TRUE(process.WaitForExit(&code)); EXPECT_EQ(0, code); if (out_pid) - *out_pid = process.pid(); + *out_pid = process.Pid(); } protected: @@ -129,7 +129,7 @@ [observer waitForNotification]; EXPECT_EQ(1, [observer receivedCount]); - EXPECT_EQ(process.pid(), [[observer object] intValue]); + EXPECT_EQ(process.Pid(), [[observer object] intValue]); } // Run the test with the sandbox enabled without notifications on the policy
diff --git a/sandbox/mac/xpc_message_server_unittest.cc b/sandbox/mac/xpc_message_server_unittest.cc index b9f905621..91975ba 100644 --- a/sandbox/mac/xpc_message_server_unittest.cc +++ b/sandbox/mac/xpc_message_server_unittest.cc
@@ -159,8 +159,8 @@ ASSERT_TRUE(child.WaitForExit(&exit_code)); EXPECT_EQ(0, exit_code); - EXPECT_EQ(child.pid(), sender_pid); - EXPECT_EQ(child.pid(), child_pid); + EXPECT_EQ(child.Pid(), sender_pid); + EXPECT_EQ(child.Pid(), child_pid); EXPECT_EQ(sender_pid, child_pid); }
diff --git a/sandbox/win/src/file_policy_test.cc b/sandbox/win/src/file_policy_test.cc index e47c6e51..199dd4c 100644 --- a/sandbox/win/src/file_policy_test.cc +++ b/sandbox/win/src/file_policy_test.cc
@@ -28,34 +28,47 @@ const ULONG kSharing = FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE; // Creates a file using different desired access. Returns if the call succeeded -// or not. The first argument in argv is the filename. If the second argument -// is "read", we try read only access. Otherwise we try read-write access. +// or not. The first argument in argv is the filename. The second argument +// determines the type of access and the dispositino of the file. SBOX_TESTS_COMMAND int File_Create(int argc, wchar_t **argv) { if (argc != 2) return SBOX_TEST_FAILED_TO_EXECUTE_COMMAND; - bool read = (_wcsicmp(argv[0], L"Read") == 0); + std::wstring operation(argv[0]); - if (read) { + if (operation == L"Read") { base::win::ScopedHandle file1(CreateFile( argv[1], GENERIC_READ, kSharing, NULL, OPEN_EXISTING, 0, NULL)); base::win::ScopedHandle file2(CreateFile( argv[1], FILE_EXECUTE, kSharing, NULL, OPEN_EXISTING, 0, NULL)); - if (file1.Get() && file2.Get()) - return SBOX_TEST_SUCCEEDED; - return SBOX_TEST_DENIED; - } else { + if (file1.IsValid() == file2.IsValid()) + return file1.IsValid() ? SBOX_TEST_SUCCEEDED : SBOX_TEST_DENIED; + return file1.IsValid() ? SBOX_TEST_FIRST_ERROR : SBOX_TEST_SECOND_ERROR; + + } else if (operation == L"Write") { base::win::ScopedHandle file1(CreateFile( argv[1], GENERIC_ALL, kSharing, NULL, OPEN_EXISTING, 0, NULL)); base::win::ScopedHandle file2(CreateFile( argv[1], GENERIC_READ | FILE_WRITE_DATA, kSharing, NULL, OPEN_EXISTING, 0, NULL)); - if (file1.Get() && file2.Get()) - return SBOX_TEST_SUCCEEDED; - return SBOX_TEST_DENIED; + if (file1.IsValid() == file2.IsValid()) + return file1.IsValid() ? SBOX_TEST_SUCCEEDED : SBOX_TEST_DENIED; + return file1.IsValid() ? SBOX_TEST_FIRST_ERROR : SBOX_TEST_SECOND_ERROR; + + } else if (operation == L"ReadCreate") { + base::win::ScopedHandle file2(CreateFile( + argv[1], GENERIC_READ, kSharing, NULL, CREATE_NEW, 0, NULL)); + base::win::ScopedHandle file1(CreateFile( + argv[1], GENERIC_READ, kSharing, NULL, CREATE_ALWAYS, 0, NULL)); + + if (file1.IsValid() == file2.IsValid()) + return file1.IsValid() ? SBOX_TEST_SUCCEEDED : SBOX_TEST_DENIED; + return file1.IsValid() ? SBOX_TEST_FIRST_ERROR : SBOX_TEST_SECOND_ERROR; } + + return SBOX_TEST_INVALID_PARAMETER; } SBOX_TESTS_COMMAND int File_Win32Create(int argc, wchar_t **argv) { @@ -295,15 +308,21 @@ wchar_t command_read[MAX_PATH + 20] = {0}; wsprintf(command_read, L"File_Create Read \"%ls\"", temp_file_name); + wchar_t command_read_create[MAX_PATH + 20] = {0}; + wsprintf(command_read_create, L"File_Create ReadCreate \"%ls\"", + temp_file_name); wchar_t command_write[MAX_PATH + 20] = {0}; wsprintf(command_write, L"File_Create Write \"%ls\"", temp_file_name); - // Verify that we have read access after revert. - EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(command_read)); + // Verify that we cannot create the file after revert. + EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command_read_create)); // Verify that we don't have write access after revert. EXPECT_EQ(SBOX_TEST_DENIED, runner.RunTest(command_write)); + // Verify that we have read access after revert. + EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(command_read)); + // Verify that we really have write access to the file. runner.SetTestState(BEFORE_REVERT); EXPECT_EQ(SBOX_TEST_SUCCEEDED, runner.RunTest(command_write));
diff --git a/sandbox/win/src/filesystem_dispatcher.cc b/sandbox/win/src/filesystem_dispatcher.cc index 354fe4f1..dcd30a7 100644 --- a/sandbox/win/src/filesystem_dispatcher.cc +++ b/sandbox/win/src/filesystem_dispatcher.cc
@@ -102,6 +102,7 @@ CountedParameterSet<OpenFile> params; params[OpenFile::NAME] = ParamPickerMake(filename); params[OpenFile::ACCESS] = ParamPickerMake(desired_access); + params[OpenFile::DISPOSITION] = ParamPickerMake(create_disposition); params[OpenFile::OPTIONS] = ParamPickerMake(create_options); params[OpenFile::BROKER] = ParamPickerMake(broker); @@ -144,9 +145,11 @@ const wchar_t* filename = name->c_str(); uint32 broker = TRUE; + uint32 create_disposition = 0; CountedParameterSet<OpenFile> params; params[OpenFile::NAME] = ParamPickerMake(filename); params[OpenFile::ACCESS] = ParamPickerMake(desired_access); + params[OpenFile::DISPOSITION] = ParamPickerMake(create_disposition); params[OpenFile::OPTIONS] = ParamPickerMake(open_options); params[OpenFile::BROKER] = ParamPickerMake(broker);
diff --git a/sandbox/win/src/filesystem_interception.cc b/sandbox/win/src/filesystem_interception.cc index 043e1fa..459f7ac 100644 --- a/sandbox/win/src/filesystem_interception.cc +++ b/sandbox/win/src/filesystem_interception.cc
@@ -54,10 +54,12 @@ uint32 desired_access_uint32 = desired_access; uint32 options_uint32 = options; + uint32 disposition_uint32 = disposition; uint32 broker = FALSE; CountedParameterSet<OpenFile> params; params[OpenFile::NAME] = ParamPickerMake(name); params[OpenFile::ACCESS] = ParamPickerMake(desired_access_uint32); + params[OpenFile::DISPOSITION] = ParamPickerMake(disposition_uint32); params[OpenFile::OPTIONS] = ParamPickerMake(options_uint32); params[OpenFile::BROKER] = ParamPickerMake(broker); @@ -128,10 +130,12 @@ uint32 desired_access_uint32 = desired_access; uint32 options_uint32 = options; + uint32 disposition_uint32 = FILE_OPEN; uint32 broker = FALSE; CountedParameterSet<OpenFile> params; params[OpenFile::NAME] = ParamPickerMake(name); params[OpenFile::ACCESS] = ParamPickerMake(desired_access_uint32); + params[OpenFile::DISPOSITION] = ParamPickerMake(disposition_uint32); params[OpenFile::OPTIONS] = ParamPickerMake(options_uint32); params[OpenFile::BROKER] = ParamPickerMake(broker);
diff --git a/sandbox/win/src/filesystem_policy.cc b/sandbox/win/src/filesystem_policy.cc index 65e8f47..1ce21c8 100644 --- a/sandbox/win/src/filesystem_policy.cc +++ b/sandbox/win/src/filesystem_policy.cc
@@ -127,7 +127,9 @@ GENERIC_READ | GENERIC_EXECUTE | READ_CONTROL; DWORD restricted_flags = ~allowed_flags; open.AddNumberMatch(IF_NOT, OpenFile::ACCESS, restricted_flags, AND); + open.AddNumberMatch(IF, OpenFile::DISPOSITION, FILE_OPEN, EQUAL); create.AddNumberMatch(IF_NOT, OpenFile::ACCESS, restricted_flags, AND); + create.AddNumberMatch(IF, OpenFile::DISPOSITION, FILE_OPEN, EQUAL); // Read only access don't work for rename. rule_to_add &= ~kCallNtSetInfoRename;
diff --git a/sandbox/win/src/policy_params.h b/sandbox/win/src/policy_params.h index f50cf1e..e051d2b 100644 --- a/sandbox/win/src/policy_params.h +++ b/sandbox/win/src/policy_params.h
@@ -23,6 +23,7 @@ POLPARAM(NAME) POLPARAM(BROKER) // TRUE if called from the broker. POLPARAM(ACCESS) + POLPARAM(DISPOSITION) POLPARAM(OPTIONS) POLPARAMS_END(OpenFile)
diff --git a/sandbox/win/src/process_mitigations.cc b/sandbox/win/src/process_mitigations.cc index 80e4284..d187c55 100644 --- a/sandbox/win/src/process_mitigations.cc +++ b/sandbox/win/src/process_mitigations.cc
@@ -8,6 +8,7 @@ #include "base/win/windows_version.h" #include "sandbox/win/src/nt_internals.h" +#include "sandbox/win/src/restricted_token_utils.h" #include "sandbox/win/src/win_utils.h" namespace { @@ -59,6 +60,13 @@ } } + if (version >= base::win::VERSION_WIN7 && + (flags & MITIGATION_HARDEN_TOKEN_IL_POLICY)) { + DWORD error = HardenProcessIntegrityLevelPolicy(); + if ((error != ERROR_SUCCESS) && (error != ERROR_ACCESS_DENIED)) + return false; + } + #if !defined(_WIN64) // DEP is always enabled on 64-bit. if (flags & MITIGATION_DEP) { DWORD dep_flags = PROCESS_DEP_ENABLE; @@ -309,7 +317,8 @@ MITIGATION_BOTTOM_UP_ASLR | MITIGATION_STRICT_HANDLE_CHECKS | MITIGATION_EXTENSION_DLL_DISABLE | - MITIGATION_DLL_SEARCH_ORDER)); + MITIGATION_DLL_SEARCH_ORDER | + MITIGATION_HARDEN_TOKEN_IL_POLICY)); } bool CanSetProcessMitigationsPreStartup(MitigationFlags flags) {
diff --git a/sandbox/win/src/restricted_token_utils.cc b/sandbox/win/src/restricted_token_utils.cc index 93b212e..5e06daa 100644 --- a/sandbox/win/src/restricted_token_utils.cc +++ b/sandbox/win/src/restricted_token_utils.cc
@@ -342,4 +342,67 @@ return SetTokenIntegrityLevel(token.Get(), integrity_level); } +DWORD HardenTokenIntegrityLevelPolicy(HANDLE token) { + if (base::win::GetVersion() < base::win::VERSION_WIN7) + return ERROR_SUCCESS; + + DWORD last_error = 0; + DWORD length_needed = 0; + + ::GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, + NULL, 0, &length_needed); + + last_error = ::GetLastError(); + if (last_error != ERROR_INSUFFICIENT_BUFFER) + return last_error; + + std::vector<char> security_desc_buffer(length_needed); + PSECURITY_DESCRIPTOR security_desc = + reinterpret_cast<PSECURITY_DESCRIPTOR>(&security_desc_buffer[0]); + + if (!::GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, + security_desc, length_needed, + &length_needed)) + return ::GetLastError(); + + PACL sacl = NULL; + BOOL sacl_present = FALSE; + BOOL sacl_defaulted = FALSE; + + if (!::GetSecurityDescriptorSacl(security_desc, &sacl_present, + &sacl, &sacl_defaulted)) + return ::GetLastError(); + + for (DWORD ace_index = 0; ace_index < sacl->AceCount; ++ace_index) { + PSYSTEM_MANDATORY_LABEL_ACE ace; + + if (::GetAce(sacl, ace_index, reinterpret_cast<LPVOID*>(&ace)) + && ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE) { + ace->Mask |= SYSTEM_MANDATORY_LABEL_NO_READ_UP + | SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP; + break; + } + } + + if (!::SetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, + security_desc)) + return ::GetLastError(); + + return ERROR_SUCCESS; +} + +DWORD HardenProcessIntegrityLevelPolicy() { + if (base::win::GetVersion() < base::win::VERSION_WIN7) + return ERROR_SUCCESS; + + HANDLE token_handle; + if (!::OpenProcessToken(GetCurrentProcess(), READ_CONTROL | WRITE_OWNER, + &token_handle)) + return ::GetLastError(); + + base::win::ScopedHandle token(token_handle); + + return HardenTokenIntegrityLevelPolicy(token.Get()); +} + } // namespace sandbox
diff --git a/sandbox/win/src/restricted_token_utils.h b/sandbox/win/src/restricted_token_utils.h index 69462b4..509feaf 100644 --- a/sandbox/win/src/restricted_token_utils.h +++ b/sandbox/win/src/restricted_token_utils.h
@@ -82,6 +82,19 @@ // current integrity level, the function will fail. DWORD SetProcessIntegrityLevel(IntegrityLevel integrity_level); +// Hardens the integrity level policy on a token. This is only valid on Win 7 +// and above. Specifically it sets the policy to block read and execute so +// that a lower privileged process cannot open the token for impersonate or +// duplicate permissions. This should limit potential security holes. +DWORD HardenTokenIntegrityLevelPolicy(HANDLE token); + +// Hardens the integrity level policy on the current process. This is only +// valid on Win 7 and above. Specifically it sets the policy to block read +// and execute so that a lower privileged process cannot open the token for +// impersonate or duplicate permissions. This should limit potential security +// holes. +DWORD HardenProcessIntegrityLevelPolicy(); + } // namespace sandbox #endif // SANDBOX_SRC_RESTRICTED_TOKEN_UTILS_H__
diff --git a/sandbox/win/src/security_level.h b/sandbox/win/src/security_level.h index da84b752..c89bbb4e 100644 --- a/sandbox/win/src/security_level.h +++ b/sandbox/win/src/security_level.h
@@ -199,6 +199,11 @@ // Must be enabled after startup. const MitigationFlags MITIGATION_DLL_SEARCH_ORDER = 0x00000001ULL << 32; +// Changes the mandatory integrity level policy on the current process' token +// to enable no-read and no-execute up. This prevents a lower IL process from +// opening the process token for impersonate/duplicate/assignment. +const MitigationFlags MITIGATION_HARDEN_TOKEN_IL_POLICY = 0x00000001ULL << 33; + } // namespace sandbox #endif // SANDBOX_SRC_SECURITY_LEVEL_H_
diff --git a/skia/BUILD.gn b/skia/BUILD.gn index 8eb6f2b0..46bd450 100644 --- a/skia/BUILD.gn +++ b/skia/BUILD.gn
@@ -375,8 +375,6 @@ "//third_party/skia/src/utils/SkCullPoints.cpp", "//third_party/skia/src/utils/SkDumpCanvas.cpp", "//third_party/skia/src/utils/SkFloatUtils.h", - "//third_party/skia/src/utils/SkGatherPixelRefsAndRects.cpp", - "//third_party/skia/src/utils/SkGatherPixelRefsAndRects.h", "//third_party/skia/src/utils/SkInterpolator.cpp", "//third_party/skia/src/utils/SkLayer.cpp", "//third_party/skia/src/utils/SkMD5.cpp",
diff --git a/skia/ext/benchmarking_canvas.cc b/skia/ext/benchmarking_canvas.cc index 5e00327..257ac3f 100644 --- a/skia/ext/benchmarking_canvas.cc +++ b/skia/ext/benchmarking_canvas.cc
@@ -210,11 +210,11 @@ AutoStamper::AutoStamper(TimingCanvas *timing_canvas) : timing_canvas_(timing_canvas) { - start_ticks_ = base::TimeTicks::HighResNow(); + start_ticks_ = base::TimeTicks::Now(); } AutoStamper::~AutoStamper() { - base::TimeDelta delta = base::TimeTicks::HighResNow() - start_ticks_; + base::TimeDelta delta = base::TimeTicks::Now() - start_ticks_; int command_index = timing_canvas_->tracking_canvas_->CommandCount() - 1; DCHECK_GE(command_index, 0); timing_canvas_->timings_map_[command_index] = delta;
diff --git a/skia/skia_library.gypi b/skia/skia_library.gypi index 36bdee6..a3903bf 100644 --- a/skia/skia_library.gypi +++ b/skia/skia_library.gypi
@@ -118,8 +118,6 @@ '../third_party/skia/src/utils/SkCullPoints.cpp', '../third_party/skia/src/utils/SkDumpCanvas.cpp', '../third_party/skia/src/utils/SkFloatUtils.h', - '../third_party/skia/src/utils/SkGatherPixelRefsAndRects.cpp', - '../third_party/skia/src/utils/SkGatherPixelRefsAndRects.h', '../third_party/skia/src/utils/SkInterpolator.cpp', '../third_party/skia/src/utils/SkLayer.cpp', '../third_party/skia/src/utils/SkMD5.cpp',
diff --git a/skia/skia_test_expectations.txt b/skia/skia_test_expectations.txt index 66ce1edd..0d92ff3 100644 --- a/skia/skia_test_expectations.txt +++ b/skia/skia_test_expectations.txt
@@ -48,44 +48,16 @@ # # START OVERRIDES HERE -# rebaselines for SK_SUPPORT_LEGACY_HQ_SCALING -crbug.com/449873 compositing/reflections/simple-composited-reflections.html [ ImageOnlyFailure Pass ] -crbug.com/449873 fast/backgrounds/repeat/negative-offset-repeat-transformed.html [ ImageOnlyFailure Pass ] -crbug.com/449873 fast/borders/border-image-rotate-transform.html [ ImageOnlyFailure Pass ] -crbug.com/449873 fast/css/resize-corner-tracking-transformed-iframe.html [ ImageOnlyFailure Pass ] -crbug.com/449873 fast/css/resize-corner-tracking-transformed.html [ ImageOnlyFailure Pass ] -crbug.com/449873 fast/images/exif-orientation-height-image-document.html [ ImageOnlyFailure Pass ] -crbug.com/449873 fast/images/exif-orientation-image-document.html [ ImageOnlyFailure Pass ] -crbug.com/449873 fast/images/exif-orientation.html [ ImageOnlyFailure Pass ] -crbug.com/449873 fast/reflections/reflection-direction.html [ ImageOnlyFailure Pass ] -crbug.com/449873 fast/reflections/reflection-masks-opacity.html [ ImageOnlyFailure Pass ] -crbug.com/449873 fast/reflections/reflection-masks-outset.html [ ImageOnlyFailure Pass ] -crbug.com/449873 fast/reflections/reflection-masks.html [ ImageOnlyFailure Pass ] -crbug.com/449873 fast/reflections/reflection-with-zoom.html [ ImageOnlyFailure Pass ] -crbug.com/449873 fast/text/international/rtl-white-space-pre-wrap.html [ ImageOnlyFailure Pass ] -crbug.com/449873 fast/text/international/unicode-bidi-plaintext-in-textarea.html [ ImageOnlyFailure Pass ] -crbug.com/449873 media/audio-repaint.html [ ImageOnlyFailure Pass ] -crbug.com/449873 scrollbars/rtl-resizer-position.html [ ImageOnlyFailure Pass ] -crbug.com/449873 svg/batik/filters/feTile.svg [ ImageOnlyFailure Pass ] -crbug.com/449873 svg/batik/text/smallFonts.svg [ ImageOnlyFailure Pass ] -crbug.com/449873 svg/batik/text/textFeatures.svg [ ImageOnlyFailure Pass ] -crbug.com/449873 svg/custom/clip-mask-negative-scale.svg [ ImageOnlyFailure Pass ] -crbug.com/449873 svg/custom/focus-ring.svg [ ImageOnlyFailure Pass ] -crbug.com/449873 svg/custom/transformed-outlines.svg [ ImageOnlyFailure Pass ] -crbug.com/449873 svg/hixie/perf/004.xml [ ImageOnlyFailure Pass ] -crbug.com/449873 virtual/antialiasedtext/fast/text/international/rtl-white-space-pre-wrap.html [ ImageOnlyFailure Pass ] -crbug.com/449873 virtual/antialiasedtext/fast/text/international/unicode-bidi-plaintext-in-textarea.html [ ImageOnlyFailure Pass ] -crbug.com/449873 virtual/deferred/fast/images/exif-orientation-height-image-document.html [ ImageOnlyFailure Pass ] -crbug.com/449873 virtual/deferred/fast/images/exif-orientation-image-document.html [ ImageOnlyFailure Pass ] -crbug.com/449873 virtual/deferred/fast/images/exif-orientation.html [ ImageOnlyFailure Pass ] -crbug.com/449873 virtual/prefer_compositing_to_lcd_text/scrollbars/rtl-resizer-position.html [ ImageOnlyFailure Pass ] -crbug.com/449873 virtual/slimmingpaint/fast/borders/border-image-rotate-transform.html [ ImageOnlyFailure Pass ] -crbug.com/449873 virtual/slimmingpaint/fast/css/resize-corner-tracking-transformed-iframe.html [ ImageOnlyFailure Pass ] -crbug.com/449873 virtual/slimmingpaint/fast/css/resize-corner-tracking-transformed.html [ ImageOnlyFailure Pass ] -crbug.com/449873 virtual/slimmingpaint/fast/images/exif-orientation-height-image-document.html [ ImageOnlyFailure Pass ] -crbug.com/449873 virtual/slimmingpaint/fast/images/exif-orientation-image-document.html [ ImageOnlyFailure Pass ] -crbug.com/449873 virtual/slimmingpaint/fast/images/exif-orientation.html [ ImageOnlyFailure Pass ] -crbug.com/449873 virtual/slimmingpaint/fast/text/international/rtl-white-space-pre-wrap.html [ ImageOnlyFailure Pass ] -crbug.com/449873 virtual/slimmingpaint/fast/text/international/unicode-bidi-plaintext-in-textarea.html [ ImageOnlyFailure Pass ] +# https://codereview.chromium.org/776673002/ +crbug.com/452219 css3/filters/effect-combined.html [ ImageOnlyFailure Pass ] +crbug.com/452219 css3/filters/effect-reference-subregion-hw.html [ ImageOnlyFailure Pass ] +crbug.com/452219 svg/W3C-SVG-1.1/filters-comptran-01-b.svg [ ImageOnlyFailure Pass ] +crbug.com/452219 svg/custom/feComponentTransfer-Discrete.svg [ ImageOnlyFailure Pass ] +crbug.com/452219 svg/custom/feComponentTransfer-Gamma.svg [ ImageOnlyFailure Pass ] +crbug.com/452219 svg/custom/feComponentTransfer-Linear.svg [ ImageOnlyFailure Pass ] +crbug.com/452219 svg/custom/feComponentTransfer-Table.svg [ ImageOnlyFailure Pass ] +crbug.com/452219 svg/dynamic-updates/SVGFEComponentTransferElement-dom-tableValues-attr.html [ ImageOnlyFailure Pass ] +crbug.com/452219 svg/dynamic-updates/SVGFEComponentTransferElement-svgdom-tableValues-prop.html [ ImageOnlyFailure Pass ] + # END OVERRIDES HERE (this line ensures that the file is newline-terminated)
diff --git a/storage/browser/BUILD.gn b/storage/browser/BUILD.gn index 3ca92d7..02bd84e 100644 --- a/storage/browser/BUILD.gn +++ b/storage/browser/BUILD.gn
@@ -7,8 +7,14 @@ output_name = "storage_browser" sources = [ "storage_browser_export.h", + "blob/blob_data_builder.cc", + "blob/blob_data_builder.h", "blob/blob_data_handle.cc", "blob/blob_data_handle.h", + "blob/blob_data_item.cc", + "blob/blob_data_item.h", + "blob/blob_data_snapshot.cc", + "blob/blob_data_snapshot.h", "blob/blob_storage_context.cc", "blob/blob_storage_context.h", "blob/blob_url_request_job.cc", @@ -19,6 +25,10 @@ "blob/file_stream_reader.h", "blob/local_file_stream_reader.cc", "blob/local_file_stream_reader.h", + "blob/scoped_file.cc", + "blob/scoped_file.h", + "blob/shareable_file_reference.cc", + "blob/shareable_file_reference.h", "blob/view_blob_internals_job.cc", "blob/view_blob_internals_job.h", "database/database_quota_client.cc",
diff --git a/storage/browser/blob/blob_data_builder.cc b/storage/browser/blob/blob_data_builder.cc new file mode 100644 index 0000000..120bc44b --- /dev/null +++ b/storage/browser/blob/blob_data_builder.cc
@@ -0,0 +1,82 @@ +// Copyright (c) 2015 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 <storage/browser/blob/blob_data_builder.h> +#include "base/time/time.h" + +namespace storage { + +BlobDataBuilder::BlobDataBuilder(const std::string& uuid) : uuid_(uuid) { +} +BlobDataBuilder::~BlobDataBuilder() { +} + +void BlobDataBuilder::AppendData(const char* data, size_t length) { + DCHECK(length > 0); + scoped_ptr<DataElement> element(new DataElement()); + element->SetToBytes(data, length); + items_.push_back(new BlobDataItem(element.Pass())); +} + +void BlobDataBuilder::AppendFile(const base::FilePath& file_path, + uint64 offset, + uint64 length, + const base::Time& expected_modification_time) { + DCHECK(length > 0); + scoped_ptr<DataElement> element(new DataElement()); + element->SetToFilePathRange(file_path, offset, length, + expected_modification_time); + items_.push_back(new BlobDataItem(element.Pass())); +} + +void BlobDataBuilder::AppendFile( + const base::FilePath& file_path, + uint64 offset, + uint64 length, + const base::Time& expected_modification_time, + scoped_refptr<ShareableFileReference> shareable_file) { + DCHECK(length > 0); + scoped_ptr<DataElement> element(new DataElement()); + element->SetToFilePathRange(file_path, offset, length, + expected_modification_time); + items_.push_back(new BlobDataItem(element.Pass(), shareable_file)); +} + +void BlobDataBuilder::AppendBlob(const std::string& uuid, + uint64 offset, + uint64 length) { + DCHECK_GT(length, 0ul); + scoped_ptr<DataElement> element(new DataElement()); + element->SetToBlobRange(uuid, offset, length); + items_.push_back(new BlobDataItem(element.Pass())); +} + +void BlobDataBuilder::AppendFileSystemFile( + const GURL& url, + uint64 offset, + uint64 length, + const base::Time& expected_modification_time) { + DCHECK(length > 0); + scoped_ptr<DataElement> element(new DataElement()); + element->SetToFileSystemUrlRange(url, offset, length, + expected_modification_time); + items_.push_back(new BlobDataItem(element.Pass())); +} + +size_t BlobDataBuilder::GetMemoryUsage() const { + int64 memory = 0; + for (const auto& data_item : items_) { + if (data_item->type() == DataElement::TYPE_BYTES) + memory += data_item->length(); + } + return memory; +} + +scoped_ptr<BlobDataSnapshot> BlobDataBuilder::BuildSnapshot() { + return scoped_ptr<BlobDataSnapshot>(new BlobDataSnapshot(uuid_, content_type_, + content_disposition_, + items_)).Pass(); +} + +} // namespace storage
diff --git a/storage/browser/blob/blob_data_builder.h b/storage/browser/blob/blob_data_builder.h new file mode 100644 index 0000000..3c426406 --- /dev/null +++ b/storage/browser/blob/blob_data_builder.h
@@ -0,0 +1,118 @@ +// Copyright 2015 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 STORAGE_BROWSER_BLOB_BLOB_DATA_BUILDER_H_ +#define STORAGE_BROWSER_BLOB_BLOB_DATA_BUILDER_H_ + +#include <string> +#include <vector> + +#include "base/basictypes.h" +#include "base/files/file_path.h" +#include "storage/browser/blob/blob_data_item.h" +#include "storage/browser/blob/blob_data_snapshot.h" +#include "storage/browser/storage_browser_export.h" + +namespace storage { +class BlobStorageContext; + +class STORAGE_EXPORT BlobDataBuilder { + public: + explicit BlobDataBuilder(const std::string& uuid); + virtual ~BlobDataBuilder(); + + const std::string& uuid() const { return uuid_; } + + void AppendData(const std::string& data) { + AppendData(data.c_str(), data.size()); + } + + void AppendData(const char* data, size_t length); + + void AppendFile(const base::FilePath& file_path, + uint64 offset, + uint64 length, + const base::Time& expected_modification_time); + + void AppendFile(const base::FilePath& file_path, + uint64 offset, + uint64 length, + const base::Time& expected_modification_time, + scoped_refptr<ShareableFileReference> shareable_file); + + void AppendBlob(const std::string& uuid, uint64 offset, uint64 length); + void AppendFileSystemFile(const GURL& url, + uint64 offset, + uint64 length, + const base::Time& expected_modification_time); + + void set_content_type(const std::string& content_type) { + content_type_ = content_type; + } + + void set_content_disposition(const std::string& content_disposition) { + content_disposition_ = content_disposition; + } + + size_t GetMemoryUsage() const; + + scoped_ptr<BlobDataSnapshot> BuildSnapshot(); + + private: + friend class BlobStorageContext; + friend bool operator==(const BlobDataBuilder& a, const BlobDataBuilder& b); + friend bool operator==(const BlobDataSnapshot& a, const BlobDataBuilder& b); + + std::string uuid_; + std::string content_type_; + std::string content_disposition_; + std::vector<scoped_refptr<BlobDataItem>> items_; + + DISALLOW_COPY_AND_ASSIGN(BlobDataBuilder); +}; + +#if defined(UNIT_TEST) +inline bool operator==(const BlobDataBuilder& a, const BlobDataBuilder& b) { + if (a.content_type_ != b.content_type_) + return false; + if (a.content_disposition_ != b.content_disposition_) + return false; + if (a.items_.size() != b.items_.size()) + return false; + for (size_t i = 0; i < a.items_.size(); ++i) { + if (a.items_[i] != b.items_[i]) + return false; + } + return true; +} + +inline bool operator==(const BlobDataSnapshot& a, const BlobDataBuilder& b) { + if (a.content_type() != b.content_type_) { + return false; + } + if (a.content_disposition() != b.content_disposition_) { + return false; + } + if (a.items().size() != b.items_.size()) { + return false; + } + for (size_t i = 0; i < a.items().size(); ++i) { + if (*(a.items()[i]) != *(b.items_[i])) { + return false; + } + } + return true; +} + +inline bool operator!=(const BlobDataSnapshot& a, const BlobDataBuilder& b) { + return !(a == b); +} + +inline bool operator!=(const BlobDataBuilder& a, const BlobDataBuilder& b) { + return !(a == b); +} +#endif // defined(UNIT_TEST) + +} // namespace storage +#endif // STORAGE_BROWSER_BLOB_BLOB_DATA_BUILDER_H_
diff --git a/storage/browser/blob/blob_data_handle.cc b/storage/browser/blob/blob_data_handle.cc index cf647b4..e3a4be94 100644 --- a/storage/browser/blob/blob_data_handle.cc +++ b/storage/browser/blob/blob_data_handle.cc
@@ -8,38 +8,38 @@ #include "base/location.h" #include "base/logging.h" #include "base/sequenced_task_runner.h" +#include "storage/browser/blob/blob_data_snapshot.h" #include "storage/browser/blob/blob_storage_context.h" -#include "storage/common/blob/blob_data.h" namespace storage { BlobDataHandle::BlobDataHandleShared::BlobDataHandleShared( - BlobData* blob_data, + const std::string& uuid, BlobStorageContext* context, base::SequencedTaskRunner* task_runner) - : blob_data_(blob_data), - context_(context->AsWeakPtr()) { - context_->IncrementBlobRefCount(blob_data->uuid()); + : uuid_(uuid), context_(context->AsWeakPtr()) { + context_->IncrementBlobRefCount(uuid); } -BlobData* BlobDataHandle::BlobDataHandleShared::data() const { - return blob_data_.get(); +scoped_ptr<BlobDataSnapshot> +BlobDataHandle::BlobDataHandleShared::CreateSnapshot() const { + return context_->CreateSnapshot(uuid_).Pass(); } const std::string& BlobDataHandle::BlobDataHandleShared::uuid() const { - return blob_data_->uuid(); + return uuid_; } BlobDataHandle::BlobDataHandleShared::~BlobDataHandleShared() { if (context_.get()) - context_->DecrementBlobRefCount(blob_data_->uuid()); + context_->DecrementBlobRefCount(uuid_); } -BlobDataHandle::BlobDataHandle(BlobData* blob_data, +BlobDataHandle::BlobDataHandle(const std::string& uuid, BlobStorageContext* context, base::SequencedTaskRunner* task_runner) : io_task_runner_(task_runner), - shared_(new BlobDataHandleShared(blob_data, context, task_runner)) { + shared_(new BlobDataHandleShared(uuid, context, task_runner)) { DCHECK(io_task_runner_.get()); DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); } @@ -52,16 +52,16 @@ BlobDataHandle::~BlobDataHandle() { BlobDataHandleShared* raw = shared_.get(); raw->AddRef(); - shared_ = 0; + shared_ = nullptr; io_task_runner_->ReleaseSoon(FROM_HERE, raw); } -BlobData* BlobDataHandle::data() const { +scoped_ptr<BlobDataSnapshot> BlobDataHandle::CreateSnapshot() const { DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); - return shared_->data(); + return shared_->CreateSnapshot().Pass(); } -std::string BlobDataHandle::uuid() const { +const std::string& BlobDataHandle::uuid() const { return shared_->uuid(); }
diff --git a/storage/browser/blob/blob_data_handle.h b/storage/browser/blob/blob_data_handle.h index 0b1d151c..30412415 100644 --- a/storage/browser/blob/blob_data_handle.h +++ b/storage/browser/blob/blob_data_handle.h
@@ -18,31 +18,44 @@ namespace storage { -class BlobData; +class BlobDataSnapshot; class BlobStorageContext; -// A scoper object for use in chrome's main browser process, ensures -// the underlying BlobData and its uuid remain in BlobStorageContext's -// collection for the duration. This object has delete semantics and -// maybe deleted on any thread. +// BlobDataHandle ensures that the underlying blob (keyed by the uuid) remains +// in the BlobStorageContext's collection while this object is alive. Anything +// that needs to keep a blob alive needs to store this handle. +// When the blob data itself is needed, clients must call the CreateSnapshot() +// method on the IO thread to create a snapshot of the blob data. This snapshot +// is not intended to be persisted, and serves to ensure that the backing +// resources remain around for the duration of reading the blob. This snapshot +// can be read on any thread, but it must be destructed on the IO thread. +// This object has delete semantics and may be deleted on any thread. class STORAGE_EXPORT BlobDataHandle : public base::SupportsUserData::Data { public: BlobDataHandle(const BlobDataHandle& other); // May be copied on any thread. - ~BlobDataHandle() override; // Maybe be deleted on any thread. - BlobData* data() const; // May only be accessed on the IO thread. + ~BlobDataHandle() override; // May be deleted on any thread. - std::string uuid() const; // May be accessed on any thread. + // A BlobDataSnapshot is used to read the data from the blob. This object is + // intended to be transient and should not be stored for any extended period + // of time. + // This call and the destruction of the returned snapshot must be called + // on the IO thread. + scoped_ptr<BlobDataSnapshot> CreateSnapshot() const; + + const std::string& uuid() const; // May be accessed on any thread. private: + // Internal class whose destructor is guarenteed to be called on the IO + // thread. class BlobDataHandleShared : public base::RefCountedThreadSafe<BlobDataHandleShared> { public: - BlobDataHandleShared(BlobData* blob_data, + BlobDataHandleShared(const std::string& uuid, BlobStorageContext* context, base::SequencedTaskRunner* task_runner); - BlobData* data() const; + scoped_ptr<BlobDataSnapshot> CreateSnapshot() const; const std::string& uuid() const; private: @@ -52,14 +65,15 @@ virtual ~BlobDataHandleShared(); - scoped_refptr<BlobData> blob_data_; + const std::string uuid_; base::WeakPtr<BlobStorageContext> context_; DISALLOW_COPY_AND_ASSIGN(BlobDataHandleShared); }; friend class BlobStorageContext; - BlobDataHandle(BlobData* blob_data, BlobStorageContext* context, + BlobDataHandle(const std::string& uuid, + BlobStorageContext* context, base::SequencedTaskRunner* task_runner); scoped_refptr<base::SequencedTaskRunner> io_task_runner_;
diff --git a/storage/browser/blob/blob_data_item.cc b/storage/browser/blob/blob_data_item.cc new file mode 100644 index 0000000..504a1c3e --- /dev/null +++ b/storage/browser/blob/blob_data_item.cc
@@ -0,0 +1,18 @@ +// Copyright (c) 2015 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 "storage/browser/blob/blob_data_item.h" + +namespace storage { + +BlobDataItem::BlobDataItem(scoped_ptr<DataElement> item, + scoped_refptr<ShareableFileReference> file_handle) + : item_(item.Pass()), file_handle_(file_handle) { +} +BlobDataItem::BlobDataItem(scoped_ptr<DataElement> item) : item_(item.Pass()) { +} +BlobDataItem::~BlobDataItem() { +} + +} // namespace storage
diff --git a/storage/browser/blob/blob_data_item.h b/storage/browser/blob/blob_data_item.h new file mode 100644 index 0000000..099415b6 --- /dev/null +++ b/storage/browser/blob/blob_data_item.h
@@ -0,0 +1,63 @@ +// Copyright (c) 2015 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 STORAGE_BROWSER_BLOB_BLOB_DATA_ITEM_H_ +#define STORAGE_BROWSER_BLOB_BLOB_DATA_ITEM_H_ + +#include "base/basictypes.h" +#include "base/memory/ref_counted.h" +#include "storage/browser/blob/shareable_file_reference.h" +#include "storage/browser/storage_browser_export.h" +#include "storage/common/data_element.h" + +namespace storage { +class BlobDataBuilder; +class BlobStorageContext; + +// Ref counted blob item. This class owns the backing data of the blob item. +// The backing data is immutable, and cannot change after creation. +// The purpose of this class is to allow the resource to stick around in the +// snapshot even after the resource was swapped in the blob (either to disk or +// to memory) by the BlobStorageContext. +class STORAGE_EXPORT BlobDataItem : public base::RefCounted<BlobDataItem> { + public: + storage::DataElement::Type type() const { return item_->type(); } + const char* bytes() const { return item_->bytes(); } + const base::FilePath& path() const { return item_->path(); } + const GURL& filesystem_url() const { return item_->filesystem_url(); } + const std::string& blob_uuid() const { return item_->blob_uuid(); } + uint64 offset() const { return item_->offset(); } + uint64 length() const { return item_->length(); } + const base::Time& expected_modification_time() const { + return item_->expected_modification_time(); + } + const DataElement& data_element() const { return *item_; } + const DataElement* data_element_ptr() const { return item_.get(); } + + private: + friend class BlobDataBuilder; + friend class BlobStorageContext; + friend class base::RefCounted<BlobDataItem>; + BlobDataItem(scoped_ptr<DataElement> item); + BlobDataItem(scoped_ptr<DataElement> item, + scoped_refptr<ShareableFileReference> file_handle); + virtual ~BlobDataItem(); + + scoped_ptr<storage::DataElement> item_; + scoped_refptr<ShareableFileReference> file_handle_; +}; + +#if defined(UNIT_TEST) +inline bool operator==(const BlobDataItem& a, const BlobDataItem& b) { + return a.data_element() == b.data_element(); +} + +inline bool operator!=(const BlobDataItem& a, const BlobDataItem& b) { + return !(a == b); +} +#endif // defined(UNIT_TEST) + +} // namespace storage + +#endif // STORAGE_BROWSER_BLOB_BLOB_DATA_ITEM_H_
diff --git a/storage/browser/blob/blob_data_snapshot.cc b/storage/browser/blob/blob_data_snapshot.cc new file mode 100644 index 0000000..6ae74cd8 --- /dev/null +++ b/storage/browser/blob/blob_data_snapshot.cc
@@ -0,0 +1,39 @@ +// Copyright (c) 2015 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 "storage/browser/blob/blob_data_snapshot.h" + +namespace storage { + +BlobDataSnapshot::BlobDataSnapshot( + const std::string& uuid, + const std::string& content_type, + const std::string& content_disposition, + const std::vector<scoped_refptr<BlobDataItem>>& items) + : uuid_(uuid), + content_type_(content_type), + content_disposition_(content_disposition), + items_(items) { +} + +BlobDataSnapshot::BlobDataSnapshot(const BlobDataSnapshot& other) + : uuid_(other.uuid_), + content_type_(other.content_type_), + content_disposition_(other.content_disposition_), + items_(other.items_) { +} + +BlobDataSnapshot::~BlobDataSnapshot() { +} + +size_t BlobDataSnapshot::GetMemoryUsage() const { + int64 memory = 0; + for (const auto& data_item : items_) { + if (data_item->type() == DataElement::TYPE_BYTES) + memory += data_item->length(); + } + return memory; +} + +} // namespace storage
diff --git a/storage/browser/blob/blob_data_snapshot.h b/storage/browser/blob/blob_data_snapshot.h new file mode 100644 index 0000000..416c386 --- /dev/null +++ b/storage/browser/blob/blob_data_snapshot.h
@@ -0,0 +1,54 @@ +// Copyright 2015 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 STORAGE_BROWSER_BLOB_BLOB_DATA_SNAPSHOT_H_ +#define STORAGE_BROWSER_BLOB_BLOB_DATA_SNAPSHOT_H_ + +#include <string> +#include <vector> + +#include "base/memory/ref_counted.h" +#include "base/supports_user_data.h" +#include "storage/browser/blob/blob_data_item.h" +#include "storage/browser/storage_browser_export.h" + +namespace storage { +class BlobDataBuilder; + +// Snapshot of a Blob. This snapshot holds a refcount of the current +// blob item resources so the backing storage for these items will stick +// around for the lifetime of this object. (The data represented by a blob is +// immutable, but the backing store can change). Keeping this object alive +// guarantees that the resources stay alive, but it does not guarentee that +// the blob stays alive. Use the BlobDataHandle to keep a blob alive. +// This class must be deleted on the IO thread. +class STORAGE_EXPORT BlobDataSnapshot : public base::SupportsUserData::Data { + public: + BlobDataSnapshot(const BlobDataSnapshot& other); + ~BlobDataSnapshot() override; + + const std::vector<scoped_refptr<BlobDataItem>>& items() const { + return items_; + } + const std::string& content_type() const { return content_type_; } + const std::string& content_disposition() const { + return content_disposition_; + } + size_t GetMemoryUsage() const; + + private: + friend class BlobDataBuilder; + BlobDataSnapshot(const std::string& uuid, + const std::string& content_type, + const std::string& content_disposition, + const std::vector<scoped_refptr<BlobDataItem>>& items); + + const std::string uuid_; + const std::string content_type_; + const std::string content_disposition_; + const std::vector<scoped_refptr<BlobDataItem>> items_; +}; + +} // namespace storage +#endif // STORAGE_BROWSER_BLOB_BLOB_DATA_SNAPSHOT_H_
diff --git a/storage/browser/blob/blob_storage_context.cc b/storage/browser/blob/blob_storage_context.cc index 9680e4d..1577b6b 100644 --- a/storage/browser/blob/blob_storage_context.cc +++ b/storage/browser/blob/blob_storage_context.cc
@@ -9,8 +9,8 @@ #include "base/logging.h" #include "base/message_loop/message_loop_proxy.h" #include "base/metrics/histogram.h" -#include "storage/browser/blob/blob_data_handle.h" -#include "storage/common/blob/blob_data.h" +#include "base/stl_util.h" +#include "storage/browser/blob/blob_data_builder.h" #include "url/gurl.h" namespace storage { @@ -43,19 +43,24 @@ : refcount(0), flags(0) { } -BlobStorageContext::BlobMapEntry::BlobMapEntry( - int refcount, int flags, BlobData* data) - : refcount(refcount), flags(flags), data(data) { +BlobStorageContext::BlobMapEntry::BlobMapEntry(int refcount, + BlobDataBuilder* data) + : refcount(refcount), flags(0), data_builder(data) { } BlobStorageContext::BlobMapEntry::~BlobMapEntry() { } +bool BlobStorageContext::BlobMapEntry::IsBeingBuilt() { + return data_builder; +} + BlobStorageContext::BlobStorageContext() : memory_usage_(0) { } BlobStorageContext::~BlobStorageContext() { + STLDeleteContainerPairSecondPointers(blob_map_.begin(), blob_map_.end()); } scoped_ptr<BlobDataHandle> BlobStorageContext::GetBlobDataFromUUID( @@ -64,11 +69,12 @@ BlobMap::iterator found = blob_map_.find(uuid); if (found == blob_map_.end()) return result.Pass(); - if (found->second.flags & EXCEEDED_MEMORY) + auto* entry = found->second; + if (entry->flags & EXCEEDED_MEMORY) return result.Pass(); - DCHECK(!(found->second.flags & BEING_BUILT)); - result.reset(new BlobDataHandle( - found->second.data.get(), this, base::MessageLoopProxy::current().get())); + DCHECK(!entry->IsBeingBuilt()); + result.reset( + new BlobDataHandle(uuid, this, base::MessageLoopProxy::current().get())); return result.Pass(); } @@ -82,16 +88,13 @@ } scoped_ptr<BlobDataHandle> BlobStorageContext::AddFinishedBlob( - const BlobData* data) { - StartBuildingBlob(data->uuid()); - for (std::vector<BlobData::Item>::const_iterator iter = - data->items().begin(); - iter != data->items().end(); ++iter) { - AppendBlobDataItem(data->uuid(), *iter); - } - FinishBuildingBlob(data->uuid(), data->content_type()); - scoped_ptr<BlobDataHandle> handle = GetBlobDataFromUUID(data->uuid()); - DecrementBlobRefCount(data->uuid()); + const BlobDataBuilder& data) { + StartBuildingBlob(data.uuid_); + for (const auto& blob_item : data.items_) + AppendBlobDataItem(data.uuid_, *(blob_item->item_)); + FinishBuildingBlob(data.uuid_, data.content_type_); + scoped_ptr<BlobDataHandle> handle = GetBlobDataFromUUID(data.uuid_); + DecrementBlobRefCount(data.uuid_); return handle.Pass(); } @@ -115,20 +118,33 @@ public_blob_urls_.erase(blob_url); } -void BlobStorageContext::StartBuildingBlob(const std::string& uuid) { - DCHECK(!IsInUse(uuid) && !uuid.empty()); - blob_map_[uuid] = BlobMapEntry(1, BEING_BUILT, new BlobData(uuid)); +scoped_ptr<BlobDataSnapshot> BlobStorageContext::CreateSnapshot( + const std::string& uuid) { + scoped_ptr<BlobDataSnapshot> result; + auto found = blob_map_.find(uuid); + DCHECK(found != blob_map_.end()) + << "Blob should be in map, as the handle is still around"; + BlobMapEntry* entry = found->second; + DCHECK(!entry->IsBeingBuilt()); + result.reset(new BlobDataSnapshot(*entry->data)); + return result.Pass(); } -void BlobStorageContext::AppendBlobDataItem( - const std::string& uuid, const BlobData::Item& item) { +void BlobStorageContext::StartBuildingBlob(const std::string& uuid) { + DCHECK(!IsInUse(uuid) && !uuid.empty()); + blob_map_[uuid] = new BlobMapEntry(1, new BlobDataBuilder(uuid)); +} + +void BlobStorageContext::AppendBlobDataItem(const std::string& uuid, + const DataElement& item) { DCHECK(IsBeingBuilt(uuid)); BlobMap::iterator found = blob_map_.find(uuid); if (found == blob_map_.end()) return; - if (found->second.flags & EXCEEDED_MEMORY) + BlobMapEntry* entry = found->second; + if (entry->flags & EXCEEDED_MEMORY) return; - BlobData* target_blob_data = found->second.data.get(); + BlobDataBuilder* target_blob_data = entry->data_builder.get(); DCHECK(target_blob_data); bool exceeded_memory = false; @@ -149,31 +165,33 @@ UMA_HISTOGRAM_COUNTS("Storage.Blob.StorageSizeBeforeAppend", memory_usage_ / 1024); switch (item.type()) { - case BlobData::Item::TYPE_BYTES: + case DataElement::TYPE_BYTES: UMA_HISTOGRAM_COUNTS("Storage.BlobItemSize.Bytes", length / 1024); DCHECK(!item.offset()); exceeded_memory = !AppendBytesItem(target_blob_data, item.bytes(), static_cast<int64>(length)); break; - case BlobData::Item::TYPE_FILE: + case DataElement::TYPE_FILE: UMA_HISTOGRAM_COUNTS("Storage.BlobItemSize.File", length / 1024); - AppendFileItem(target_blob_data, item.path(), item.offset(), length, - item.expected_modification_time()); + AppendFileItem(target_blob_data, item.path(), item.offset(), + item.length(), item.expected_modification_time()); break; - case BlobData::Item::TYPE_FILE_FILESYSTEM: + case DataElement::TYPE_FILE_FILESYSTEM: UMA_HISTOGRAM_COUNTS("Storage.BlobItemSize.FileSystem", length / 1024); AppendFileSystemFileItem(target_blob_data, item.filesystem_url(), - item.offset(), length, + item.offset(), item.length(), item.expected_modification_time()); break; - case BlobData::Item::TYPE_BLOB: { + case DataElement::TYPE_BLOB: { UMA_HISTOGRAM_COUNTS("Storage.BlobItemSize.Blob", length / 1024); + // We grab the handle to ensure it stays around while we copy it. scoped_ptr<BlobDataHandle> src = GetBlobDataFromUUID(item.blob_uuid()); - if (src) - exceeded_memory = !ExpandStorageItems(target_blob_data, - src->data(), - item.offset(), - item.length()); + if (src) { + BlobMapEntry* entry = blob_map_.find(item.blob_uuid())->second; + DCHECK(entry->data); + exceeded_memory = !ExpandStorageItems(target_blob_data, *entry->data, + item.offset(), item.length()); + } break; } default: @@ -188,8 +206,8 @@ // as a stop gap, we'll prevent memory usage over a max amount. if (exceeded_memory) { memory_usage_ -= target_blob_data->GetMemoryUsage(); - found->second.flags |= EXCEEDED_MEMORY; - found->second.data = new BlobData(uuid); + entry->flags |= EXCEEDED_MEMORY; + entry->data_builder.reset(new BlobDataBuilder(uuid)); return; } } @@ -200,13 +218,13 @@ BlobMap::iterator found = blob_map_.find(uuid); if (found == blob_map_.end()) return; - found->second.data->set_content_type(content_type); - found->second.flags &= ~BEING_BUILT; - UMA_HISTOGRAM_COUNTS("Storage.Blob.ItemCount", - found->second.data->items().size()); - UMA_HISTOGRAM_BOOLEAN( - "Storage.Blob.ExceededMemory", - (found->second.flags & EXCEEDED_MEMORY) == EXCEEDED_MEMORY); + BlobMapEntry* entry = found->second; + entry->data_builder->set_content_type(content_type); + entry->data = entry->data_builder->BuildSnapshot().Pass(); + entry->data_builder.reset(); + UMA_HISTOGRAM_COUNTS("Storage.Blob.ItemCount", entry->data->items().size()); + UMA_HISTOGRAM_BOOLEAN("Storage.Blob.ExceededMemory", + (entry->flags & EXCEEDED_MEMORY) == EXCEEDED_MEMORY); } void BlobStorageContext::CancelBuildingBlob(const std::string& uuid) { @@ -220,60 +238,63 @@ DCHECK(false); return; } - ++(found->second.refcount); + ++(found->second->refcount); } void BlobStorageContext::DecrementBlobRefCount(const std::string& uuid) { BlobMap::iterator found = blob_map_.find(uuid); if (found == blob_map_.end()) return; - DCHECK_EQ(found->second.data->uuid(), uuid); - if (--(found->second.refcount) == 0) { - memory_usage_ -= found->second.data->GetMemoryUsage(); + auto* entry = found->second; + if (--(entry->refcount) == 0) { + if (entry->IsBeingBuilt()) { + memory_usage_ -= entry->data_builder->GetMemoryUsage(); + } else { + memory_usage_ -= entry->data->GetMemoryUsage(); + } + delete entry; blob_map_.erase(found); } } bool BlobStorageContext::ExpandStorageItems( - BlobData* target_blob_data, BlobData* src_blob_data, - uint64 offset, uint64 length) { - DCHECK(target_blob_data && src_blob_data && - length != static_cast<uint64>(-1)); + BlobDataBuilder* target_blob_data, + const BlobDataSnapshot& src_blob_data, + uint64 offset, + uint64 length) { + DCHECK(target_blob_data && length != static_cast<uint64>(-1)); - std::vector<BlobData::Item>::const_iterator iter = - src_blob_data->items().begin(); + const std::vector<scoped_refptr<BlobDataItem>>& items = src_blob_data.items(); + auto iter = items.begin(); if (offset) { - for (; iter != src_blob_data->items().end(); ++iter) { - if (offset >= iter->length()) - offset -= iter->length(); + for (; iter != items.end(); ++iter) { + const BlobDataItem& item = *(iter->get()); + if (offset >= item.length()) + offset -= item.length(); else break; } } - for (; iter != src_blob_data->items().end() && length > 0; ++iter) { - uint64 current_length = iter->length() - offset; + for (; iter != items.end() && length > 0; ++iter) { + const BlobDataItem& item = *(iter->get()); + uint64 current_length = item.length() - offset; uint64 new_length = current_length > length ? length : current_length; - if (iter->type() == BlobData::Item::TYPE_BYTES) { + if (iter->get()->type() == DataElement::TYPE_BYTES) { if (!AppendBytesItem( target_blob_data, - iter->bytes() + static_cast<size_t>(iter->offset() + offset), + item.bytes() + static_cast<size_t>(item.offset() + offset), static_cast<int64>(new_length))) { return false; // exceeded memory } - } else if (iter->type() == BlobData::Item::TYPE_FILE) { - AppendFileItem(target_blob_data, - iter->path(), - iter->offset() + offset, - new_length, - iter->expected_modification_time()); + } else if (item.type() == DataElement::TYPE_FILE) { + AppendFileItem(target_blob_data, item.path(), item.offset() + offset, + new_length, item.expected_modification_time()); } else { - DCHECK(iter->type() == BlobData::Item::TYPE_FILE_FILESYSTEM); - AppendFileSystemFileItem(target_blob_data, - iter->filesystem_url(), - iter->offset() + offset, - new_length, - iter->expected_modification_time()); + DCHECK(item.type() == DataElement::TYPE_FILE_FILESYSTEM); + AppendFileSystemFileItem(target_blob_data, item.filesystem_url(), + item.offset() + offset, new_length, + item.expected_modification_time()); } length -= new_length; offset = 0; @@ -281,36 +302,40 @@ return true; } -bool BlobStorageContext::AppendBytesItem( - BlobData* target_blob_data, const char* bytes, int64 length) { +bool BlobStorageContext::AppendBytesItem(BlobDataBuilder* target_blob_data, + const char* bytes, + int64 length) { if (length < 0) { DCHECK(false); return false; } - if (memory_usage_ + length > kMaxMemoryUsage) + if (memory_usage_ + length > kMaxMemoryUsage) { return false; + } target_blob_data->AppendData(bytes, static_cast<size_t>(length)); memory_usage_ += length; return true; } void BlobStorageContext::AppendFileItem( - BlobData* target_blob_data, - const base::FilePath& file_path, uint64 offset, uint64 length, + BlobDataBuilder* target_blob_data, + const base::FilePath& file_path, + uint64 offset, + uint64 length, const base::Time& expected_modification_time) { - target_blob_data->AppendFile(file_path, offset, length, - expected_modification_time); - // It may be a temporary file that should be deleted when no longer needed. scoped_refptr<ShareableFileReference> shareable_file = ShareableFileReference::Get(file_path); - if (shareable_file.get()) - target_blob_data->AttachShareableFileReference(shareable_file.get()); + + target_blob_data->AppendFile(file_path, offset, length, + expected_modification_time, shareable_file); } void BlobStorageContext::AppendFileSystemFileItem( - BlobData* target_blob_data, - const GURL& filesystem_url, uint64 offset, uint64 length, + BlobDataBuilder* target_blob_data, + const GURL& filesystem_url, + uint64 offset, + uint64 length, const base::Time& expected_modification_time) { target_blob_data->AppendFileSystemFile(filesystem_url, offset, length, expected_modification_time); @@ -324,7 +349,7 @@ BlobMap::iterator found = blob_map_.find(uuid); if (found == blob_map_.end()) return false; - return found->second.flags & BEING_BUILT; + return found->second->IsBeingBuilt(); } bool BlobStorageContext::IsUrlRegistered(const GURL& blob_url) {
diff --git a/storage/browser/blob/blob_storage_context.h b/storage/browser/blob/blob_storage_context.h index 7ccc133..322a4c6 100644 --- a/storage/browser/blob/blob_storage_context.h +++ b/storage/browser/blob/blob_storage_context.h
@@ -12,8 +12,9 @@ #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "storage/browser/blob/blob_data_handle.h" +#include "storage/browser/blob/blob_data_snapshot.h" #include "storage/browser/storage_browser_export.h" -#include "storage/common/blob/blob_data.h" +#include "storage/common/data_element.h" class GURL; @@ -29,6 +30,7 @@ namespace storage { class BlobDataHandle; +class BlobDataBuilder; // This class handles the logistics of blob Storage within the browser process, // and maintains a mapping from blob uuid to the data. The class is single @@ -45,7 +47,7 @@ // Useful for coining blobs from within the browser process. If the // blob cannot be added due to memory consumption, returns NULL. - scoped_ptr<BlobDataHandle> AddFinishedBlob(const BlobData* blob_data); + scoped_ptr<BlobDataHandle> AddFinishedBlob(const BlobDataBuilder& blob_data); // Useful for coining blob urls from within the browser process. bool RegisterPublicBlobURL(const GURL& url, const std::string& uuid); @@ -57,46 +59,54 @@ friend class ViewBlobInternalsJob; enum EntryFlags { - BEING_BUILT = 1 << 0, EXCEEDED_MEMORY = 1 << 1, }; struct BlobMapEntry { int refcount; int flags; - scoped_refptr<BlobData> data; + // data and data_builder are mutually exclusive. + scoped_ptr<BlobDataSnapshot> data; + scoped_ptr<BlobDataBuilder> data_builder; BlobMapEntry(); - BlobMapEntry(int refcount, int flags, BlobData* data); + BlobMapEntry(int refcount, BlobDataBuilder* data); ~BlobMapEntry(); + + bool IsBeingBuilt(); }; - typedef std::map<std::string, BlobMapEntry> - BlobMap; + typedef std::map<std::string, BlobMapEntry*> BlobMap; typedef std::map<GURL, std::string> BlobURLMap; + // Called by BlobDataHandle. + scoped_ptr<BlobDataSnapshot> CreateSnapshot(const std::string& uuid); + void StartBuildingBlob(const std::string& uuid); void AppendBlobDataItem(const std::string& uuid, - const BlobData::Item& data_item); + const DataElement& data_item); void FinishBuildingBlob(const std::string& uuid, const std::string& type); void CancelBuildingBlob(const std::string& uuid); void IncrementBlobRefCount(const std::string& uuid); void DecrementBlobRefCount(const std::string& uuid); - bool ExpandStorageItems(BlobData* target_blob_data, - BlobData* src_blob_data, + bool ExpandStorageItems(BlobDataBuilder* target_blob_data, + const BlobDataSnapshot& src_blob_data, uint64 offset, uint64 length); - bool AppendBytesItem(BlobData* target_blob_data, - const char* data, int64 length); - void AppendFileItem(BlobData* target_blob_data, + bool AppendBytesItem(BlobDataBuilder* target_blob_data, + const char* data, + int64 length); + void AppendFileItem(BlobDataBuilder* target_blob_data, const base::FilePath& file_path, - uint64 offset, uint64 length, + uint64 offset, + uint64 length, const base::Time& expected_modification_time); - void AppendFileSystemFileItem( - BlobData* target_blob_data, - const GURL& url, uint64 offset, uint64 length, - const base::Time& expected_modification_time); + void AppendFileSystemFileItem(BlobDataBuilder* target_blob_data, + const GURL& url, + uint64 offset, + uint64 length, + const base::Time& expected_modification_time); bool IsInUse(const std::string& uuid); bool IsBeingBuilt(const std::string& uuid);
diff --git a/storage/browser/blob/blob_url_request_job.cc b/storage/browser/blob/blob_url_request_job.cc index 41e7942..068b5c4 100644 --- a/storage/browser/blob/blob_url_request_job.cc +++ b/storage/browser/blob/blob_url_request_job.cc
@@ -34,15 +34,16 @@ #include "storage/browser/blob/file_stream_reader.h" #include "storage/browser/fileapi/file_system_context.h" #include "storage/browser/fileapi/file_system_url.h" +#include "storage/common/data_element.h" namespace storage { namespace { -bool IsFileType(BlobData::Item::Type type) { +bool IsFileType(DataElement::Type type) { switch (type) { - case BlobData::Item::TYPE_FILE: - case BlobData::Item::TYPE_FILE_FILESYSTEM: + case DataElement::TYPE_FILE: + case DataElement::TYPE_FILE_FILESYSTEM: return true; default: return false; @@ -54,11 +55,11 @@ BlobURLRequestJob::BlobURLRequestJob( net::URLRequest* request, net::NetworkDelegate* network_delegate, - const scoped_refptr<BlobData>& blob_data, + scoped_ptr<BlobDataSnapshot> blob_data, storage::FileSystemContext* file_system_context, base::MessageLoopProxy* file_thread_proxy) : net::URLRequestJob(request, network_delegate), - blob_data_(blob_data), + blob_data_(blob_data.Pass()), file_system_context_(file_system_context), file_thread_proxy_(file_thread_proxy), total_size_(0), @@ -174,7 +175,7 @@ } // If the blob data is not present, bail out. - if (!blob_data_.get()) { + if (!blob_data_) { NotifyFailure(net::ERR_FILE_NOT_FOUND); return; } @@ -198,10 +199,11 @@ void BlobURLRequestJob::CountSize() { pending_get_file_info_count_ = 0; total_size_ = 0; - item_length_list_.resize(blob_data_->items().size()); + const auto& items = blob_data_->items(); + item_length_list_.resize(items.size()); - for (size_t i = 0; i < blob_data_->items().size(); ++i) { - const BlobData::Item& item = blob_data_->items().at(i); + for (size_t i = 0; i < items.size(); ++i) { + const BlobDataItem& item = *items.at(i); if (IsFileType(item.type())) { ++pending_get_file_info_count_; GetFileStreamReader(i)->GetLength( @@ -257,8 +259,9 @@ return; } - DCHECK_LT(index, blob_data_->items().size()); - const BlobData::Item& item = blob_data_->items().at(index); + const auto& items = blob_data_->items(); + DCHECK_LT(index, items.size()); + const BlobDataItem& item = *items.at(index); DCHECK(IsFileType(item.type())); uint64 file_length = result; @@ -290,8 +293,9 @@ void BlobURLRequestJob::Seek(int64 offset) { // Skip the initial items that are not in the range. + const auto& items = blob_data_->items(); for (current_item_index_ = 0; - current_item_index_ < blob_data_->items().size() && + current_item_index_ < items.size() && offset >= item_length_list_[current_item_index_]; ++current_item_index_) { offset -= item_length_list_[current_item_index_]; @@ -304,7 +308,7 @@ return; // Adjust the offset of the first stream if it is of file type. - const BlobData::Item& item = blob_data_->items().at(current_item_index_); + const BlobDataItem& item = *items.at(current_item_index_); if (IsFileType(item.type())) { DeleteCurrentFileReader(); CreateFileStreamReader(current_item_index_, offset); @@ -316,9 +320,10 @@ if (remaining_bytes_ == 0) return true; + const auto& items = blob_data_->items(); // If we get to the last item but still expect something to read, bail out // since something is wrong. - if (current_item_index_ >= blob_data_->items().size()) { + if (current_item_index_ >= items.size()) { NotifyFailure(net::ERR_FAILED); return false; } @@ -333,8 +338,8 @@ } // Do the reading. - const BlobData::Item& item = blob_data_->items().at(current_item_index_); - if (item.type() == BlobData::Item::TYPE_BYTES) + const BlobDataItem& item = *items.at(current_item_index_); + if (item.type() == DataElement::TYPE_BYTES) return ReadBytesItem(item, bytes_to_read); if (IsFileType(item.type())) { return ReadFileItem(GetFileStreamReader(current_item_index_), @@ -370,7 +375,7 @@ DCHECK_GE(read_buf_->BytesRemaining(), 0); } -bool BlobURLRequestJob::ReadBytesItem(const BlobData::Item& item, +bool BlobURLRequestJob::ReadBytesItem(const BlobDataItem& item, int bytes_to_read) { DCHECK_GE(read_buf_->BytesRemaining(), bytes_to_read); @@ -555,8 +560,9 @@ } FileStreamReader* BlobURLRequestJob::GetFileStreamReader(size_t index) { - DCHECK_LT(index, blob_data_->items().size()); - const BlobData::Item& item = blob_data_->items().at(index); + const auto& items = blob_data_->items(); + DCHECK_LT(index, items.size()); + const BlobDataItem& item = *items.at(index); if (!IsFileType(item.type())) return NULL; if (index_to_reader_.find(index) == index_to_reader_.end()) @@ -567,21 +573,22 @@ void BlobURLRequestJob::CreateFileStreamReader(size_t index, int64 additional_offset) { - DCHECK_LT(index, blob_data_->items().size()); - const BlobData::Item& item = blob_data_->items().at(index); + const auto& items = blob_data_->items(); + DCHECK_LT(index, items.size()); + const BlobDataItem& item = *items.at(index); DCHECK(IsFileType(item.type())); DCHECK_EQ(0U, index_to_reader_.count(index)); FileStreamReader* reader = NULL; switch (item.type()) { - case BlobData::Item::TYPE_FILE: + case DataElement::TYPE_FILE: reader = FileStreamReader::CreateForLocalFile( file_thread_proxy_.get(), item.path(), item.offset() + additional_offset, item.expected_modification_time()); break; - case BlobData::Item::TYPE_FILE_FILESYSTEM: + case DataElement::TYPE_FILE_FILESYSTEM: reader = file_system_context_ ->CreateFileStreamReader( storage::FileSystemURL(file_system_context_->CrackURL(
diff --git a/storage/browser/blob/blob_url_request_job.h b/storage/browser/blob/blob_url_request_job.h index dab61dc7..cf296b6 100644 --- a/storage/browser/blob/blob_url_request_job.h +++ b/storage/browser/blob/blob_url_request_job.h
@@ -12,8 +12,8 @@ #include "net/http/http_byte_range.h" #include "net/http/http_status_code.h" #include "net/url_request/url_request_job.h" +#include "storage/browser/blob/blob_data_snapshot.h" #include "storage/browser/storage_browser_export.h" -#include "storage/common/blob/blob_data.h" namespace base { class MessageLoopProxy; @@ -38,7 +38,7 @@ public: BlobURLRequestJob(net::URLRequest* request, net::NetworkDelegate* network_delegate, - const scoped_refptr<BlobData>& blob_data, + scoped_ptr<BlobDataSnapshot> blob_data, storage::FileSystemContext* file_system_context, base::MessageLoopProxy* resolving_message_loop_proxy); @@ -70,7 +70,7 @@ bool ReadItem(); void AdvanceItem(); void AdvanceBytesRead(int result); - bool ReadBytesItem(const BlobData::Item& item, int bytes_to_read); + bool ReadBytesItem(const BlobDataItem& item, int bytes_to_read); bool ReadFileItem(FileStreamReader* reader, int bytes_to_read); void DidReadFile(int result); @@ -92,7 +92,7 @@ // Creates a FileStreamReader for the item at |index| with additional_offset. void CreateFileStreamReader(size_t index, int64 additional_offset); - scoped_refptr<BlobData> blob_data_; + scoped_ptr<BlobDataSnapshot> blob_data_; // Variables for controlling read from |blob_data_|. scoped_refptr<storage::FileSystemContext> file_system_context_;
diff --git a/storage/browser/blob/blob_url_request_job_factory.cc b/storage/browser/blob/blob_url_request_job_factory.cc index 60f9c738..fe193af 100644 --- a/storage/browser/blob/blob_url_request_job_factory.cc +++ b/storage/browser/blob/blob_url_request_job_factory.cc
@@ -68,11 +68,11 @@ file_loop_proxy_.get()); } -scoped_refptr<storage::BlobData> BlobProtocolHandler::LookupBlobData( +scoped_ptr<BlobDataSnapshot> BlobProtocolHandler::LookupBlobData( net::URLRequest* request) const { BlobDataHandle* blob_data_handle = GetRequestedBlobDataHandle(request); if (blob_data_handle) - return blob_data_handle->data(); + return blob_data_handle->CreateSnapshot().Pass(); if (!context_.get()) return NULL; @@ -84,7 +84,12 @@ return NULL; std::string uuid = request->url().spec().substr(kPrefix.length()); scoped_ptr<BlobDataHandle> handle = context_->GetBlobDataFromUUID(uuid); - return handle.get() ? handle->data() : NULL; + scoped_ptr<BlobDataSnapshot> snapshot; + if (handle) { + snapshot = handle->CreateSnapshot().Pass(); + SetRequestedBlobDataHandle(request, handle.Pass()); + } + return snapshot.Pass(); } } // namespace storage
diff --git a/storage/browser/blob/blob_url_request_job_factory.h b/storage/browser/blob/blob_url_request_job_factory.h index c3e34e3..381a95fc 100644 --- a/storage/browser/blob/blob_url_request_job_factory.h +++ b/storage/browser/blob/blob_url_request_job_factory.h
@@ -26,7 +26,7 @@ namespace storage { -class BlobData; +class BlobDataSnapshot; class BlobDataHandle; class BlobStorageContext; @@ -56,8 +56,7 @@ net::NetworkDelegate* network_delegate) const override; private: - scoped_refptr<BlobData> LookupBlobData( - net::URLRequest* request) const; + scoped_ptr<BlobDataSnapshot> LookupBlobData(net::URLRequest* request) const; base::WeakPtr<BlobStorageContext> context_; const scoped_refptr<storage::FileSystemContext> file_system_context_;
diff --git a/storage/common/blob/scoped_file.cc b/storage/browser/blob/scoped_file.cc similarity index 97% rename from storage/common/blob/scoped_file.cc rename to storage/browser/blob/scoped_file.cc index b544449..cdf4cb8 100644 --- a/storage/common/blob/scoped_file.cc +++ b/storage/browser/blob/scoped_file.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 "storage/common/blob/scoped_file.h" +#include "storage/browser/blob/scoped_file.h" #include "base/bind.h" #include "base/callback.h"
diff --git a/storage/common/blob/scoped_file.h b/storage/browser/blob/scoped_file.h similarity index 92% rename from storage/common/blob/scoped_file.h rename to storage/browser/blob/scoped_file.h index 4a51a46..a8fd730 100644 --- a/storage/common/blob/scoped_file.h +++ b/storage/browser/blob/scoped_file.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 STORAGE_COMMON_BLOB_SCOPED_FILE_H_ -#define STORAGE_COMMON_BLOB_SCOPED_FILE_H_ +#ifndef STORAGE_BROWSER_BLOB_SCOPED_FILE_H_ +#define STORAGE_BROWSER_BLOB_SCOPED_FILE_H_ #include <map> @@ -11,7 +11,7 @@ #include "base/files/file_path.h" #include "base/memory/ref_counted.h" #include "base/move.h" -#include "storage/common/storage_common_export.h" +#include "storage/browser/storage_browser_export.h" namespace base { class TaskRunner; @@ -26,7 +26,7 @@ // // TODO(kinuko): Probably this can be moved under base or somewhere more // common place. -class STORAGE_COMMON_EXPORT ScopedFile { +class STORAGE_EXPORT ScopedFile { // To support destructive assignment from an l-value assignment. // This provides Pass() method which creates an r-value for the current // instance. (See base/move.h for details) @@ -91,4 +91,4 @@ } // namespace storage -#endif // STORAGE_COMMON_BLOB_SCOPED_FILE_H_ +#endif // STORAGE_BROWSER_BLOB_SCOPED_FILE_H_
diff --git a/storage/common/blob/shareable_file_reference.cc b/storage/browser/blob/shareable_file_reference.cc similarity index 98% rename from storage/common/blob/shareable_file_reference.cc rename to storage/browser/blob/shareable_file_reference.cc index c2ec839..02a5be4 100644 --- a/storage/common/blob/shareable_file_reference.cc +++ b/storage/browser/blob/shareable_file_reference.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 "storage/common/blob/shareable_file_reference.h" +#include "storage/browser/blob/shareable_file_reference.h" #include <map>
diff --git a/storage/common/blob/shareable_file_reference.h b/storage/browser/blob/shareable_file_reference.h similarity index 88% rename from storage/common/blob/shareable_file_reference.h rename to storage/browser/blob/shareable_file_reference.h index bd9d0503..e2739dc 100644 --- a/storage/common/blob/shareable_file_reference.h +++ b/storage/browser/blob/shareable_file_reference.h
@@ -2,12 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef STORAGE_COMMON_BLOB_SHAREABLE_FILE_REFERENCE_H_ -#define STORAGE_COMMON_BLOB_SHAREABLE_FILE_REFERENCE_H_ +#ifndef STORAGE_BROWSER_BLOB_SHAREABLE_FILE_REFERENCE_H_ +#define STORAGE_BROWSER_BLOB_SHAREABLE_FILE_REFERENCE_H_ #include <vector> -#include "storage/common/blob/scoped_file.h" +#include "storage/browser/blob/scoped_file.h" +#include "storage/browser/storage_browser_export.h" namespace storage { @@ -15,7 +16,7 @@ // same path if it already exists in its internal map. // This class is non-thread-safe and all methods must be called on a single // thread. -class STORAGE_COMMON_EXPORT ShareableFileReference +class STORAGE_EXPORT ShareableFileReference : public base::RefCounted<ShareableFileReference> { public: typedef ScopedFile::ScopeOutCallback FinalReleaseCallback; @@ -71,4 +72,4 @@ } // namespace storage -#endif // STORAGE_COMMON_BLOB_SHAREABLE_FILE_REFERENCE_H_ +#endif // STORAGE_BROWSER_BLOB_SHAREABLE_FILE_REFERENCE_H_
diff --git a/storage/browser/blob/view_blob_internals_job.cc b/storage/browser/blob/view_blob_internals_job.cc index 2065a31..3f5cc41 100644 --- a/storage/browser/blob/view_blob_internals_job.cc +++ b/storage/browser/blob/view_blob_internals_job.cc
@@ -18,8 +18,8 @@ #include "net/base/escape.h" #include "net/base/net_errors.h" #include "net/url_request/url_request.h" +#include "storage/browser/blob/blob_data_snapshot.h" #include "storage/browser/blob/blob_storage_context.h" -#include "storage/common/blob/blob_data.h" namespace { @@ -150,8 +150,7 @@ iter != blob_storage_context_->blob_map_.end(); ++iter) { AddHTMLBoldText(iter->first, out); - GenerateHTMLForBlobData(*(iter->second.data.get()), - iter->second.refcount, + GenerateHTMLForBlobData(*(iter->second->data.get()), iter->second->refcount, out); } if (!blob_storage_context_->public_blob_urls_.empty()) { @@ -168,9 +167,10 @@ } } -void ViewBlobInternalsJob::GenerateHTMLForBlobData(const BlobData& blob_data, - int refcount, - std::string* out) { +void ViewBlobInternalsJob::GenerateHTMLForBlobData( + const BlobDataSnapshot& blob_data, + int refcount, + std::string* out) { StartHTMLList(out); AddHTMLListItem(kRefcount, base::IntToString(refcount), out); @@ -190,13 +190,13 @@ AddHTMLListItem(kIndex, base::UTF16ToUTF8(base::FormatNumber(i)), out); StartHTMLList(out); } - const BlobData::Item& item = blob_data.items().at(i); + const BlobDataItem& item = *(blob_data.items().at(i)); switch (item.type()) { - case BlobData::Item::TYPE_BYTES: + case DataElement::TYPE_BYTES: AddHTMLListItem(kType, "data", out); break; - case BlobData::Item::TYPE_FILE: + case DataElement::TYPE_FILE: AddHTMLListItem(kType, "file", out); AddHTMLListItem(kPath, net::EscapeForHTML(item.path().AsUTF8Unsafe()), @@ -207,10 +207,10 @@ out); } break; - case BlobData::Item::TYPE_BLOB: + case DataElement::TYPE_BLOB: NOTREACHED(); // Should be flattened in the storage context. break; - case BlobData::Item::TYPE_FILE_FILESYSTEM: + case DataElement::TYPE_FILE_FILESYSTEM: AddHTMLListItem(kType, "filesystem", out); AddHTMLListItem(kURL, item.filesystem_url().spec(), out); if (!item.expected_modification_time().is_null()) { @@ -219,7 +219,7 @@ out); } break; - case BlobData::Item::TYPE_UNKNOWN: + case DataElement::TYPE_UNKNOWN: NOTREACHED(); break; }
diff --git a/storage/browser/blob/view_blob_internals_job.h b/storage/browser/blob/view_blob_internals_job.h index 4ab1e30..2abb1d4 100644 --- a/storage/browser/blob/view_blob_internals_job.h +++ b/storage/browser/blob/view_blob_internals_job.h
@@ -17,7 +17,7 @@ namespace storage { -class BlobData; +class BlobDataSnapshot; class BlobStorageContext; // A job subclass that implements a protocol to inspect the internal @@ -41,7 +41,7 @@ ~ViewBlobInternalsJob() override; void GenerateHTML(std::string* out) const; - static void GenerateHTMLForBlobData(const BlobData& blob_data, + static void GenerateHTMLForBlobData(const BlobDataSnapshot& blob_data, int refcount, std::string* out);
diff --git a/storage/browser/fileapi/async_file_util_adapter.cc b/storage/browser/fileapi/async_file_util_adapter.cc index 3bb20f9..7d324c0 100644 --- a/storage/browser/fileapi/async_file_util_adapter.cc +++ b/storage/browser/fileapi/async_file_util_adapter.cc
@@ -10,11 +10,11 @@ #include "base/sequenced_task_runner.h" #include "base/task_runner_util.h" #include "base/thread_task_runner_handle.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" #include "storage/browser/fileapi/file_system_operation_context.h" #include "storage/browser/fileapi/file_system_url.h" -#include "storage/common/blob/shareable_file_reference.h" #include "storage/common/fileapi/file_system_util.h" using base::Bind;
diff --git a/storage/browser/fileapi/copy_or_move_operation_delegate.cc b/storage/browser/fileapi/copy_or_move_operation_delegate.cc index 1b95f79..baa93db4 100644 --- a/storage/browser/fileapi/copy_or_move_operation_delegate.cc +++ b/storage/browser/fileapi/copy_or_move_operation_delegate.cc
@@ -9,6 +9,7 @@ #include "net/base/io_buffer.h" #include "net/base/net_errors.h" #include "storage/browser/blob/file_stream_reader.h" +#include "storage/browser/blob/shareable_file_reference.h" #include "storage/browser/fileapi/copy_or_move_file_validator.h" #include "storage/browser/fileapi/file_observers.h" #include "storage/browser/fileapi/file_stream_writer.h" @@ -16,7 +17,6 @@ #include "storage/browser/fileapi/file_system_operation_runner.h" #include "storage/browser/fileapi/file_system_url.h" #include "storage/browser/fileapi/recursive_operation_delegate.h" -#include "storage/common/blob/shareable_file_reference.h" #include "storage/common/fileapi/file_system_util.h" namespace storage {
diff --git a/storage/browser/fileapi/dragged_file_util.cc b/storage/browser/fileapi/dragged_file_util.cc index 9a5b66e..ff581fe3 100644 --- a/storage/browser/fileapi/dragged_file_util.cc +++ b/storage/browser/fileapi/dragged_file_util.cc
@@ -8,12 +8,12 @@ #include <vector> #include "base/files/file_util.h" +#include "storage/browser/blob/shareable_file_reference.h" #include "storage/browser/fileapi/file_system_context.h" #include "storage/browser/fileapi/file_system_operation_context.h" #include "storage/browser/fileapi/file_system_url.h" #include "storage/browser/fileapi/isolated_context.h" #include "storage/browser/fileapi/native_file_util.h" -#include "storage/common/blob/shareable_file_reference.h" namespace storage {
diff --git a/storage/browser/fileapi/file_system_file_stream_reader.h b/storage/browser/fileapi/file_system_file_stream_reader.h index b0a718a3..c0cdeb1c 100644 --- a/storage/browser/fileapi/file_system_file_stream_reader.h +++ b/storage/browser/fileapi/file_system_file_stream_reader.h
@@ -10,9 +10,9 @@ #include "base/memory/ref_counted.h" #include "base/time/time.h" #include "storage/browser/blob/file_stream_reader.h" +#include "storage/browser/blob/shareable_file_reference.h" #include "storage/browser/fileapi/file_system_url.h" #include "storage/browser/storage_browser_export.h" -#include "storage/common/blob/shareable_file_reference.h" namespace base { class FilePath;
diff --git a/storage/browser/fileapi/file_system_file_util.h b/storage/browser/fileapi/file_system_file_util.h index c649c31..48a127a 100644 --- a/storage/browser/fileapi/file_system_file_util.h +++ b/storage/browser/fileapi/file_system_file_util.h
@@ -8,9 +8,9 @@ #include "base/files/file.h" #include "base/files/file_path.h" #include "base/memory/scoped_ptr.h" +#include "storage/browser/blob/scoped_file.h" #include "storage/browser/fileapi/file_system_operation.h" #include "storage/browser/storage_browser_export.h" -#include "storage/common/blob/scoped_file.h" namespace base { class Time;
diff --git a/storage/browser/fileapi/file_system_operation_impl.cc b/storage/browser/fileapi/file_system_operation_impl.cc index 25613dd..dbca3d6 100644 --- a/storage/browser/fileapi/file_system_operation_impl.cc +++ b/storage/browser/fileapi/file_system_operation_impl.cc
@@ -10,6 +10,7 @@ #include "base/time/time.h" #include "net/base/escape.h" #include "net/url_request/url_request.h" +#include "storage/browser/blob/shareable_file_reference.h" #include "storage/browser/fileapi/async_file_util.h" #include "storage/browser/fileapi/copy_or_move_operation_delegate.h" #include "storage/browser/fileapi/file_observers.h" @@ -22,7 +23,6 @@ #include "storage/browser/fileapi/remove_operation_delegate.h" #include "storage/browser/fileapi/sandbox_file_system_backend.h" #include "storage/browser/quota/quota_manager_proxy.h" -#include "storage/common/blob/shareable_file_reference.h" #include "storage/common/fileapi/file_system_types.h" #include "storage/common/fileapi/file_system_util.h" #include "storage/common/quota/quota_types.h"
diff --git a/storage/browser/fileapi/file_system_operation_impl.h b/storage/browser/fileapi/file_system_operation_impl.h index add6b7c..dbf6e3a 100644 --- a/storage/browser/fileapi/file_system_operation_impl.h +++ b/storage/browser/fileapi/file_system_operation_impl.h
@@ -10,12 +10,12 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" +#include "storage/browser/blob/scoped_file.h" #include "storage/browser/fileapi/file_system_operation.h" #include "storage/browser/fileapi/file_system_operation_context.h" #include "storage/browser/fileapi/file_system_url.h" #include "storage/browser/fileapi/file_writer_delegate.h" #include "storage/browser/storage_browser_export.h" -#include "storage/common/blob/scoped_file.h" #include "storage/common/quota/quota_types.h" namespace storage {
diff --git a/storage/browser/fileapi/file_system_operation_runner.cc b/storage/browser/fileapi/file_system_operation_runner.cc index 9c1e4a6..848929f38 100644 --- a/storage/browser/fileapi/file_system_operation_runner.cc +++ b/storage/browser/fileapi/file_system_operation_runner.cc
@@ -9,12 +9,12 @@ #include "base/stl_util.h" #include "net/url_request/url_request_context.h" #include "storage/browser/blob/blob_url_request_job_factory.h" +#include "storage/browser/blob/shareable_file_reference.h" #include "storage/browser/fileapi/file_observers.h" #include "storage/browser/fileapi/file_stream_writer.h" #include "storage/browser/fileapi/file_system_context.h" #include "storage/browser/fileapi/file_system_operation.h" #include "storage/browser/fileapi/file_writer_delegate.h" -#include "storage/common/blob/shareable_file_reference.h" namespace storage {
diff --git a/storage/browser/fileapi/obfuscated_file_util.h b/storage/browser/fileapi/obfuscated_file_util.h index 090e55e3..b8fab48c 100644 --- a/storage/browser/fileapi/obfuscated_file_util.h +++ b/storage/browser/fileapi/obfuscated_file_util.h
@@ -16,12 +16,12 @@ #include "base/files/file_util_proxy.h" #include "base/gtest_prod_util.h" #include "base/memory/scoped_ptr.h" +#include "storage/browser/blob/shareable_file_reference.h" #include "storage/browser/fileapi/file_system_file_util.h" #include "storage/browser/fileapi/file_system_url.h" #include "storage/browser/fileapi/sandbox_directory_database.h" #include "storage/browser/fileapi/sandbox_file_system_backend_delegate.h" #include "storage/browser/storage_browser_export.h" -#include "storage/common/blob/shareable_file_reference.h" #include "storage/common/fileapi/file_system_types.h" namespace base {
diff --git a/storage/browser/fileapi/sandbox_file_stream_writer.h b/storage/browser/fileapi/sandbox_file_stream_writer.h index 69b3136..61375b11 100644 --- a/storage/browser/fileapi/sandbox_file_stream_writer.h +++ b/storage/browser/fileapi/sandbox_file_stream_writer.h
@@ -8,11 +8,11 @@ #include "base/files/file.h" #include "base/files/file_path.h" #include "base/memory/scoped_ptr.h" +#include "storage/browser/blob/shareable_file_reference.h" #include "storage/browser/fileapi/file_stream_writer.h" #include "storage/browser/fileapi/file_system_url.h" #include "storage/browser/fileapi/task_runner_bound_observer_list.h" #include "storage/browser/storage_browser_export.h" -#include "storage/common/blob/shareable_file_reference.h" #include "storage/common/fileapi/file_system_types.h" #include "storage/common/quota/quota_types.h" #include "url/gurl.h"
diff --git a/storage/common/BUILD.gn b/storage/common/BUILD.gn index 5212a92..0067972 100644 --- a/storage/common/BUILD.gn +++ b/storage/common/BUILD.gn
@@ -9,12 +9,6 @@ "data_element.cc", "data_element.h", "storage_common_export.h", - "blob/blob_data.cc", - "blob/blob_data.h", - "blob/scoped_file.cc", - "blob/scoped_file.h", - "blob/shareable_file_reference.cc", - "blob/shareable_file_reference.h", "database/database_connections.cc", "database/database_connections.h", "database/database_identifier.cc",
diff --git a/storage/common/blob/blob_data.cc b/storage/common/blob/blob_data.cc deleted file mode 100644 index 23f73e3f..0000000 --- a/storage/common/blob/blob_data.cc +++ /dev/null
@@ -1,63 +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 "storage/common/blob/blob_data.h" - -#include "base/logging.h" -#include "base/strings/sys_string_conversions.h" -#include "base/strings/utf_string_conversions.h" -#include "base/time/time.h" - -namespace storage { - -BlobData::BlobData() {} -BlobData::BlobData(const std::string& uuid) - : uuid_(uuid) { -} - -BlobData::~BlobData() {} - -void BlobData::AppendData(const char* data, size_t length) { - DCHECK(length > 0); - items_.push_back(Item()); - items_.back().SetToBytes(data, length); -} - -void BlobData::AppendFile(const base::FilePath& file_path, - uint64 offset, uint64 length, - const base::Time& expected_modification_time) { - DCHECK(length > 0); - items_.push_back(Item()); - items_.back().SetToFilePathRange(file_path, offset, length, - expected_modification_time); -} - -void BlobData::AppendBlob(const std::string& uuid, - uint64 offset, uint64 length) { - DCHECK_GT(length, 0ul); - items_.push_back(Item()); - items_.back().SetToBlobRange(uuid, offset, length); -} - -void BlobData::AppendFileSystemFile( - const GURL& url, uint64 offset, - uint64 length, - const base::Time& expected_modification_time) { - DCHECK(length > 0); - items_.push_back(Item()); - items_.back().SetToFileSystemUrlRange(url, offset, length, - expected_modification_time); -} - -int64 BlobData::GetMemoryUsage() const { - int64 memory = 0; - for (std::vector<Item>::const_iterator iter = items_.begin(); - iter != items_.end(); ++iter) { - if (iter->type() == Item::TYPE_BYTES) - memory += iter->length(); - } - return memory; -} - -} // namespace storage
diff --git a/storage/common/blob/blob_data.h b/storage/common/blob/blob_data.h deleted file mode 100644 index 2f485465..0000000 --- a/storage/common/blob/blob_data.h +++ /dev/null
@@ -1,98 +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 STORAGE_COMMON_BLOB_BLOB_DATA_H_ -#define STORAGE_COMMON_BLOB_BLOB_DATA_H_ - -#include <string> -#include <vector> - -#include "base/basictypes.h" -#include "base/files/file_path.h" -#include "base/memory/ref_counted.h" -#include "base/time/time.h" -#include "storage/common/blob/shareable_file_reference.h" -#include "storage/common/data_element.h" -#include "storage/common/storage_common_export.h" -#include "url/gurl.h" - -namespace storage { - -class STORAGE_COMMON_EXPORT BlobData - : public base::RefCounted<BlobData> { - public: - typedef storage::DataElement Item; - - // TODO(michaeln): remove the empty ctor when we fully transition to uuids. - BlobData(); - explicit BlobData(const std::string& uuid); - - void AppendData(const std::string& data) { - AppendData(data.c_str(), data.size()); - } - - void AppendData(const char* data, size_t length); - - void AppendFile(const base::FilePath& file_path, uint64 offset, uint64 length, - const base::Time& expected_modification_time); - void AppendBlob(const std::string& uuid, uint64 offset, uint64 length); - void AppendFileSystemFile(const GURL& url, uint64 offset, uint64 length, - const base::Time& expected_modification_time); - - void AttachShareableFileReference(ShareableFileReference* reference) { - shareable_files_.push_back(reference); - } - - const std::string& uuid() const { return uuid_; } - const std::vector<Item>& items() const { return items_; } - const std::string& content_type() const { return content_type_; } - void set_content_type(const std::string& content_type) { - content_type_ = content_type; - } - - const std::string& content_disposition() const { - return content_disposition_; - } - void set_content_disposition(const std::string& content_disposition) { - content_disposition_ = content_disposition; - } - - int64 GetMemoryUsage() const; - - private: - friend class base::RefCounted<BlobData>; - virtual ~BlobData(); - - std::string uuid_; - std::string content_type_; - std::string content_disposition_; - std::vector<Item> items_; - std::vector<scoped_refptr<ShareableFileReference> > shareable_files_; - - DISALLOW_COPY_AND_ASSIGN(BlobData); -}; - -#if defined(UNIT_TEST) -inline bool operator==(const BlobData& a, const BlobData& b) { - if (a.content_type() != b.content_type()) - return false; - if (a.content_disposition() != b.content_disposition()) - return false; - if (a.items().size() != b.items().size()) - return false; - for (size_t i = 0; i < a.items().size(); ++i) { - if (a.items()[i] != b.items()[i]) - return false; - } - return true; -} - -inline bool operator!=(const BlobData& a, const BlobData& b) { - return !(a == b); -} -#endif // defined(UNIT_TEST) - -} // namespace storage - -#endif // STORAGE_COMMON_BLOB_BLOB_DATA_H_
diff --git a/storage/common/data_element.h b/storage/common/data_element.h index bdc8812..0efe1550 100644 --- a/storage/common/data_element.h +++ b/storage/common/data_element.h
@@ -50,8 +50,28 @@ length_ = buf_.size(); } + // Sets TYPE_BYTES data, and clears the internal bytes buffer. + // For use with AppendBytes. + void SetToEmptyBytes() { + type_ = TYPE_BYTES; + buf_.clear(); + length_ = 0; + bytes_ = nullptr; + } + + // Copies and appends the given data into the element. SetToEmptyBytes or + // SetToBytes must be called before this method. + void AppendBytes(const char* bytes, int bytes_len) { + DCHECK_EQ(type_, TYPE_BYTES); + DCHECK_NE(length_, kuint64max); + DCHECK(!bytes_); + buf_.insert(buf_.end(), bytes, bytes + bytes_len); + length_ = buf_.size(); + } + // Sets TYPE_BYTES data. This does NOT copy the given data and the caller // should make sure the data is alive when this element is accessed. + // You cannot use AppendBytes with this method. void SetToSharedBytes(const char* bytes, int bytes_len) { type_ = TYPE_BYTES; bytes_ = bytes;
diff --git a/storage/storage_browser.gyp b/storage/storage_browser.gyp index 2ec504f..5f93ecf78 100644 --- a/storage/storage_browser.gyp +++ b/storage/storage_browser.gyp
@@ -25,8 +25,14 @@ ], 'defines': ['STORAGE_BROWSER_IMPLEMENTATION'], 'sources': [ + 'browser/blob/blob_data_builder.cc', + 'browser/blob/blob_data_builder.h', 'browser/blob/blob_data_handle.cc', 'browser/blob/blob_data_handle.h', + 'browser/blob/blob_data_item.cc', + 'browser/blob/blob_data_item.h', + 'browser/blob/blob_data_snapshot.cc', + 'browser/blob/blob_data_snapshot.h', 'browser/blob/blob_storage_context.cc', 'browser/blob/blob_storage_context.h', 'browser/blob/blob_url_request_job.cc', @@ -37,6 +43,10 @@ 'browser/blob/file_stream_reader.h', 'browser/blob/local_file_stream_reader.cc', 'browser/blob/local_file_stream_reader.h', + 'browser/blob/scoped_file.cc', + 'browser/blob/scoped_file.h', + 'browser/blob/shareable_file_reference.cc', + 'browser/blob/shareable_file_reference.h', 'browser/blob/view_blob_internals_job.cc', 'browser/blob/view_blob_internals_job.h', 'browser/database/database_quota_client.cc',
diff --git a/storage/storage_common.gyp b/storage/storage_common.gyp index 87d34b9..74b91391 100644 --- a/storage/storage_common.gyp +++ b/storage/storage_common.gyp
@@ -22,12 +22,6 @@ 'sources': [ 'common/data_element.cc', 'common/data_element.h', - 'common/blob/blob_data.cc', - 'common/blob/blob_data.h', - 'common/blob/scoped_file.cc', - 'common/blob/scoped_file.h', - 'common/blob/shareable_file_reference.cc', - 'common/blob/shareable_file_reference.h', 'common/database/database_connections.cc', 'common/database/database_connections.h', 'common/database/database_identifier.cc',
diff --git a/sync/android/java/src/org/chromium/sync/AndroidSyncSettings.java b/sync/android/java/src/org/chromium/sync/AndroidSyncSettings.java new file mode 100644 index 0000000..99d66da --- /dev/null +++ b/sync/android/java/src/org/chromium/sync/AndroidSyncSettings.java
@@ -0,0 +1,432 @@ +// Copyright 2015 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.sync; + +import android.accounts.Account; +import android.content.ContentResolver; +import android.content.Context; +import android.content.SyncStatusObserver; +import android.os.StrictMode; + +import org.chromium.base.ObserverList; +import org.chromium.base.VisibleForTesting; +import org.chromium.sync.signin.AccountManagerHelper; +import org.chromium.sync.signin.ChromeSigninController; + +import javax.annotation.concurrent.NotThreadSafe; +import javax.annotation.concurrent.ThreadSafe; + +/** + * A helper class to handle the current status of sync for Chrome in Android settings. + * + * It also provides an observer to be used whenever Android sync settings change. + * + * To retrieve an instance of this class, call AndroidSyncSettings.get(someContext). + * + * All new public methods MUST call notifyObservers at the end. + */ +@ThreadSafe +public class AndroidSyncSettings { + + /** + * In-memory holder of the sync configurations for a given account. On each + * access, updates the cache if the account has changed. This lazy-updating + * model is appropriate as the account changes rarely but may not be known + * when initially constructed. So long as we keep a single account, no + * expensive calls to Android are made. + */ + @NotThreadSafe + @VisibleForTesting + public static class CachedAccountSyncSettings { + private final String mContractAuthority; + private final SyncContentResolverDelegate mSyncContentResolverDelegate; + private Account mAccount; + private boolean mDidUpdate; + private boolean mSyncAutomatically; + private int mIsSyncable; + + public CachedAccountSyncSettings(String contractAuthority, + SyncContentResolverDelegate contentResolverWrapper) { + mContractAuthority = contractAuthority; + mSyncContentResolverDelegate = contentResolverWrapper; + } + + private void ensureSettingsAreForAccount(Account account) { + assert account != null; + if (account.equals(mAccount)) return; + updateSyncSettingsForAccount(account); + mDidUpdate = true; + } + + public void clearUpdateStatus() { + mDidUpdate = false; + } + + public boolean getDidUpdateStatus() { + return mDidUpdate; + } + + // Calling this method may have side-effects. + public boolean getSyncAutomatically(Account account) { + ensureSettingsAreForAccount(account); + return mSyncAutomatically; + } + + public void updateSyncSettingsForAccount(Account account) { + if (account == null) return; + updateSyncSettingsForAccountInternal(account); + } + + public void setIsSyncable(Account account) { + ensureSettingsAreForAccount(account); + if (mIsSyncable == 1) return; + setIsSyncableInternal(account); + } + + public void setSyncAutomatically(Account account, boolean value) { + ensureSettingsAreForAccount(account); + if (mSyncAutomatically == value) return; + setSyncAutomaticallyInternal(account, value); + } + + @VisibleForTesting + protected void updateSyncSettingsForAccountInternal(Account account) { + // Null check here otherwise Findbugs complains. + if (account == null) return; + + boolean oldSyncAutomatically = mSyncAutomatically; + int oldIsSyncable = mIsSyncable; + Account oldAccount = mAccount; + + mAccount = account; + + StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites(); + mSyncAutomatically = mSyncContentResolverDelegate.getSyncAutomatically( + account, mContractAuthority); + mIsSyncable = mSyncContentResolverDelegate.getIsSyncable(account, mContractAuthority); + StrictMode.setThreadPolicy(oldPolicy); + mDidUpdate = (oldIsSyncable != mIsSyncable) + || (oldSyncAutomatically != mSyncAutomatically) + || (!account.equals(oldAccount)); + } + + @VisibleForTesting + protected void setIsSyncableInternal(Account account) { + mIsSyncable = 1; + StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites(); + mSyncContentResolverDelegate.setIsSyncable(account, mContractAuthority, 1); + StrictMode.setThreadPolicy(oldPolicy); + mDidUpdate = true; + } + + @VisibleForTesting + protected void setSyncAutomaticallyInternal(Account account, boolean value) { + mSyncAutomatically = value; + StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites(); + mSyncContentResolverDelegate.setSyncAutomatically(account, mContractAuthority, value); + StrictMode.setThreadPolicy(oldPolicy); + mDidUpdate = true; + } + } + + public static final String TAG = "AndroidSyncSettings"; + + /** + * Lock for ensuring singleton instantiation across threads. + */ + private static final Object INSTANCE_LOCK = new Object(); + + private static AndroidSyncSettings sAndroidSyncSettings; + + private final String mContractAuthority; + + private final Context mApplicationContext; + + private final SyncContentResolverDelegate mSyncContentResolverDelegate; + + private boolean mCachedMasterSyncAutomatically; + + // Instantiation of AndroidSyncSettings is guarded by a lock so volatile is unneeded. + private CachedAccountSyncSettings mCachedSettings; + + private final ObserverList<AndroidSyncSettingsObserver> mObservers = + new ObserverList<AndroidSyncSettingsObserver>(); + + /** + * Provides notifications when Android sync settings have changed. + */ + public interface AndroidSyncSettingsObserver { + public void androidSyncSettingsChanged(); + } + + /** + * @param context the context + * @param syncContentResolverDelegate an implementation of {@link SyncContentResolverDelegate}. + */ + private AndroidSyncSettings(Context context, + SyncContentResolverDelegate syncContentResolverDelegate, + CachedAccountSyncSettings cachedAccountSettings) { + mApplicationContext = context.getApplicationContext(); + mSyncContentResolverDelegate = syncContentResolverDelegate; + mContractAuthority = getContractAuthority(); + mCachedSettings = cachedAccountSettings; + + updateMasterSyncAutomaticallySetting(); + + mSyncContentResolverDelegate.addStatusChangeListener( + ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS, + new AndroidSyncSettingsChangedObserver()); + } + + private void updateMasterSyncAutomaticallySetting() { + StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites(); + synchronized (mCachedSettings) { + mCachedMasterSyncAutomatically = mSyncContentResolverDelegate + .getMasterSyncAutomatically(); + } + StrictMode.setThreadPolicy(oldPolicy); + } + + /** + * A factory method for the AndroidSyncSettings. + * + * It is possible to override the {@link SyncContentResolverDelegate} to use in tests for the + * instance of the AndroidSyncSettings by calling overrideAndroidSyncSettingsForTests(...) with + * your {@link SyncContentResolverDelegate}. + * + * @param context the ApplicationContext is retrieved from the context used as an argument. + * @return a singleton instance of the AndroidSyncSettings + */ + public static AndroidSyncSettings get(Context context) { + synchronized (INSTANCE_LOCK) { + if (sAndroidSyncSettings == null) { + SyncContentResolverDelegate contentResolverDelegate = + new SystemSyncContentResolverDelegate(); + CachedAccountSyncSettings cache = new CachedAccountSyncSettings( + context.getPackageName(), contentResolverDelegate); + sAndroidSyncSettings = new AndroidSyncSettings( + context, contentResolverDelegate, cache); + } + } + return sAndroidSyncSettings; + } + + /** + * Tests might want to consider overriding the context and {@link SyncContentResolverDelegate} + * so they do not use the real ContentResolver in Android. + * + * @param context the context to use + * @param syncContentResolverDelegate the {@link SyncContentResolverDelegate} to use + */ + @VisibleForTesting + public static void overrideAndroidSyncSettingsForTests(Context context, + SyncContentResolverDelegate syncContentResolverDelegate, + CachedAccountSyncSettings cachedAccountSettings) { + synchronized (INSTANCE_LOCK) { + if (sAndroidSyncSettings != null) { + throw new IllegalStateException("AndroidSyncSettings already exists"); + } + sAndroidSyncSettings = new AndroidSyncSettings(context, syncContentResolverDelegate, + cachedAccountSettings); + } + } + + @VisibleForTesting + public static void overrideAndroidSyncSettingsForTests(Context context, + SyncContentResolverDelegate syncContentResolverDelegate) { + CachedAccountSyncSettings cachedAccountSettings = new CachedAccountSyncSettings( + context.getPackageName(), syncContentResolverDelegate); + overrideAndroidSyncSettingsForTests(context, syncContentResolverDelegate, + cachedAccountSettings); + } + + /** + * Returns the contract authority to use when requesting sync. + */ + public String getContractAuthority() { + return mApplicationContext.getPackageName(); + } + + /** + * Add a new AndroidSyncSettingsObserver. + */ + public void registerObserver(AndroidSyncSettingsObserver observer) { + mObservers.addObserver(observer); + } + + /** + * Remove an AndroidSyncSettingsObserver that was previously added. + */ + public void unregisterObserver(AndroidSyncSettingsObserver observer) { + mObservers.removeObserver(observer); + } + + /** + * Checks whether sync is currently enabled from Chrome for a given account. + * + * It checks both the master sync for the device, and Chrome sync setting for the given account. + * + * @param account the account to check if Chrome sync is enabled on. + * @return true if sync is on, false otherwise + */ + public boolean isSyncEnabled(Account account) { + if (account == null) return false; + boolean returnValue; + synchronized (mCachedSettings) { + returnValue = mCachedMasterSyncAutomatically + && mCachedSettings.getSyncAutomatically(account); + } + + notifyObserversIfAccountSettingsChanged(); + return returnValue; + } + + /** + * Checks whether sync is currently enabled from Chrome for the currently signed in account. + * + * It checks both the master sync for the device, and Chrome sync setting for the given account. + * If no user is currently signed in it returns false. + * + * @return true if sync is on, false otherwise + */ + public boolean isSyncEnabled() { + return isSyncEnabled(ChromeSigninController.get(mApplicationContext).getSignedInUser()); + } + + /** + * Checks whether sync is currently enabled from Chrome for a given account. + * + * It checks only Chrome sync setting for the given account, + * and ignores the master sync setting. + * + * @param account the account to check if Chrome sync is enabled on. + * @return true if sync is on, false otherwise + */ + public boolean isChromeSyncEnabled(Account account) { + if (account == null) return false; + + boolean returnValue; + synchronized (mCachedSettings) { + returnValue = mCachedSettings.getSyncAutomatically(account); + } + + notifyObserversIfAccountSettingsChanged(); + return returnValue; + } + + /** + * Checks whether the master sync flag for Android is currently set. + * + * @return true if the global master sync is on, false otherwise + */ + public boolean isMasterSyncEnabled() { + synchronized (mCachedSettings) { + return mCachedMasterSyncAutomatically; + } + } + + /** + * Make sure Chrome is syncable, and enable sync. + * + * @param account the account to enable sync on + */ + public void enableChromeSync(Account account) { + makeSyncable(account); + + synchronized (mCachedSettings) { + mCachedSettings.setSyncAutomatically(account, true); + } + + notifyObserversIfAccountSettingsChanged(); + } + + /** + * Disables Android Chrome sync + * + * @param account the account to disable Chrome sync on + */ + public void disableChromeSync(Account account) { + synchronized (mCachedSettings) { + mCachedSettings.setSyncAutomatically(account, false); + } + + notifyObserversIfAccountSettingsChanged(); + } + + /** + * Register with Android Sync Manager. This is what causes the "Chrome" option to appear in + * Settings -> Accounts / Sync . + * + * @param account the account to enable Chrome sync on + */ + private void makeSyncable(Account account) { + synchronized (mCachedSettings) { + mCachedSettings.setIsSyncable(account); + } + + StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites(); + // Disable the syncability of Chrome for all other accounts. Don't use + // our cache as we're touching many accounts that aren't signed in, so this saves + // extra calls to Android sync configuration. + Account[] googleAccounts = AccountManagerHelper.get(mApplicationContext) + .getGoogleAccounts(); + for (Account accountToSetNotSyncable : googleAccounts) { + if (!accountToSetNotSyncable.equals(account) + && mSyncContentResolverDelegate.getIsSyncable( + accountToSetNotSyncable, mContractAuthority) > 0) { + mSyncContentResolverDelegate.setIsSyncable(accountToSetNotSyncable, + mContractAuthority, 0); + } + } + StrictMode.setThreadPolicy(oldPolicy); + } + + /** + * Helper class to be used by observers whenever sync settings change. + * + * To register the observer, call AndroidSyncSettings.registerObserver(...). + */ + private class AndroidSyncSettingsChangedObserver implements SyncStatusObserver { + @Override + public void onStatusChanged(int which) { + if (ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS == which) { + // Sync settings have changed; update our in-memory caches + synchronized (mCachedSettings) { + mCachedSettings.updateSyncSettingsForAccount( + ChromeSigninController.get(mApplicationContext).getSignedInUser()); + } + + boolean oldMasterSyncEnabled = isMasterSyncEnabled(); + updateMasterSyncAutomaticallySetting(); + boolean didMasterSyncChanged = oldMasterSyncEnabled != isMasterSyncEnabled(); + // Notify observers if MasterSync or account level settings change. + if (didMasterSyncChanged || getAndClearDidUpdateStatus()) { + notifyObservers(); + } + } + } + } + + private boolean getAndClearDidUpdateStatus() { + boolean didGetStatusUpdate; + synchronized (mCachedSettings) { + didGetStatusUpdate = mCachedSettings.getDidUpdateStatus(); + mCachedSettings.clearUpdateStatus(); + } + return didGetStatusUpdate; + } + + private void notifyObserversIfAccountSettingsChanged() { + if (getAndClearDidUpdateStatus()) { + notifyObservers(); + } + } + + private void notifyObservers() { + for (AndroidSyncSettingsObserver observer : mObservers) { + observer.androidSyncSettingsChanged(); + } + } +}
diff --git a/sync/android/java/src/org/chromium/sync/SyncConstants.java b/sync/android/java/src/org/chromium/sync/SyncConstants.java new file mode 100644 index 0000000..7d6c84b --- /dev/null +++ b/sync/android/java/src/org/chromium/sync/SyncConstants.java
@@ -0,0 +1,15 @@ +// Copyright 2015 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.sync; + +/** This class stores constants that need to be in org.chromium.sync. */ +public final class SyncConstants { + + // This should always have the same value as GaiaConstants::kChromeSyncOAuth2Scope. + public static final String CHROME_SYNC_OAUTH2_SCOPE = + "https://www.googleapis.com/auth/chromesync"; + + private SyncConstants() {} +}
diff --git a/sync/android/java/src/org/chromium/sync/notifier/SyncContentResolverDelegate.java b/sync/android/java/src/org/chromium/sync/SyncContentResolverDelegate.java similarity index 96% rename from sync/android/java/src/org/chromium/sync/notifier/SyncContentResolverDelegate.java rename to sync/android/java/src/org/chromium/sync/SyncContentResolverDelegate.java index 016a930..85ab19f 100644 --- a/sync/android/java/src/org/chromium/sync/notifier/SyncContentResolverDelegate.java +++ b/sync/android/java/src/org/chromium/sync/SyncContentResolverDelegate.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.sync.notifier; +package org.chromium.sync; import android.accounts.Account;
diff --git a/sync/android/java/src/org/chromium/sync/notifier/SystemSyncContentResolverDelegate.java b/sync/android/java/src/org/chromium/sync/SystemSyncContentResolverDelegate.java similarity index 93% rename from sync/android/java/src/org/chromium/sync/notifier/SystemSyncContentResolverDelegate.java rename to sync/android/java/src/org/chromium/sync/SystemSyncContentResolverDelegate.java index 1df37115..9e8cd7d 100644 --- a/sync/android/java/src/org/chromium/sync/notifier/SystemSyncContentResolverDelegate.java +++ b/sync/android/java/src/org/chromium/sync/SystemSyncContentResolverDelegate.java
@@ -2,13 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.sync.notifier; +package org.chromium.sync; import android.accounts.Account; import android.content.ContentResolver; import android.content.SyncStatusObserver; +/** + * A SyncContentResolverDelegate that simply forwards calls to ContentResolver. + */ public class SystemSyncContentResolverDelegate implements SyncContentResolverDelegate { @Override
diff --git a/sync/android/java/src/org/chromium/sync/notifier/SyncStatusHelper.java b/sync/android/java/src/org/chromium/sync/notifier/SyncStatusHelper.java index a25a786..7660434d 100644 --- a/sync/android/java/src/org/chromium/sync/notifier/SyncStatusHelper.java +++ b/sync/android/java/src/org/chromium/sync/notifier/SyncStatusHelper.java
@@ -12,6 +12,8 @@ import org.chromium.base.ObserverList; import org.chromium.base.VisibleForTesting; +import org.chromium.sync.SyncContentResolverDelegate; +import org.chromium.sync.SystemSyncContentResolverDelegate; import org.chromium.sync.signin.AccountManagerHelper; import org.chromium.sync.signin.ChromeSigninController;
diff --git a/sync/android/javatests/src/org/chromium/sync/notifier/signin/SyncStatusHelperTest.java b/sync/android/javatests/src/org/chromium/sync/AndroidSyncSettingsTest.java similarity index 82% rename from sync/android/javatests/src/org/chromium/sync/notifier/signin/SyncStatusHelperTest.java rename to sync/android/javatests/src/org/chromium/sync/AndroidSyncSettingsTest.java index c9b5d33..f3dea91 100644 --- a/sync/android/javatests/src/org/chromium/sync/notifier/signin/SyncStatusHelperTest.java +++ b/sync/android/javatests/src/org/chromium/sync/AndroidSyncSettingsTest.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.sync.notifier.signin; +package org.chromium.sync; import android.accounts.Account; import android.content.Context; @@ -11,13 +11,15 @@ import org.chromium.base.ThreadUtils; import org.chromium.base.test.util.Feature; -import org.chromium.sync.notifier.SyncStatusHelper; -import org.chromium.sync.notifier.SyncStatusHelper.CachedAccountSyncSettings; -import org.chromium.sync.notifier.SyncStatusHelper.SyncSettingsChangedObserver; +import org.chromium.sync.AndroidSyncSettings.AndroidSyncSettingsObserver; +import org.chromium.sync.AndroidSyncSettings.CachedAccountSyncSettings; import org.chromium.sync.signin.ChromeSigninController; import org.chromium.sync.test.util.MockSyncContentResolverDelegate; -public class SyncStatusHelperTest extends InstrumentationTestCase { +/** + * Tests for AndroidSyncSettings. + */ +public class AndroidSyncSettingsTest extends InstrumentationTestCase { private static class CountingMockSyncContentResolverDelegate extends MockSyncContentResolverDelegate { @@ -91,7 +93,7 @@ } } - private static class MockSyncSettingsObserver implements SyncSettingsChangedObserver { + private static class MockSyncSettingsObserver implements AndroidSyncSettingsObserver { private boolean mReceivedNotification; public void clearNotification() { @@ -103,12 +105,12 @@ } @Override - public void syncSettingsChanged() { + public void androidSyncSettingsChanged() { mReceivedNotification = true; } } - private SyncStatusHelper mHelper; + private AndroidSyncSettings mAndroid; private CountingMockSyncContentResolverDelegate mSyncContentResolverDelegate; private String mAuthority; private Account mTestAccount; @@ -122,21 +124,21 @@ Context context = getInstrumentation().getTargetContext(); mCachedAccountSyncSettings = new CountingCachedAccountSyncSettings( context.getPackageName(), mSyncContentResolverDelegate); - SyncStatusHelper.overrideSyncStatusHelperForTests( + AndroidSyncSettings.overrideAndroidSyncSettingsForTests( context, mSyncContentResolverDelegate, mCachedAccountSyncSettings); - mHelper = SyncStatusHelper.get(getInstrumentation().getTargetContext()); + mAndroid = AndroidSyncSettings.get(getInstrumentation().getTargetContext()); // Need to set the signed in account name to ensure that sync settings notifications // update the right account. ChromeSigninController.get( getInstrumentation().getTargetContext()).setSignedInAccountName( "account@example.com"); - mAuthority = SyncStatusHelper.get(getInstrumentation().getTargetContext()) + mAuthority = AndroidSyncSettings.get(getInstrumentation().getTargetContext()) .getContractAuthority(); mTestAccount = new Account("account@example.com", "com.google"); mAlternateTestAccount = new Account("alternateAccount@example.com", "com.google"); mSyncSettingsObserver = new MockSyncSettingsObserver(); - mHelper.registerSyncSettingsChangedObserver(mSyncSettingsObserver); + mAndroid.registerObserver(mSyncSettingsObserver); super.setUp(); } @@ -146,11 +148,11 @@ public void testToggleMasterSyncAutomaticallyFromSettings() throws InterruptedException { mSyncContentResolverDelegate.setMasterSyncAutomatically(true); mSyncContentResolverDelegate.waitForLastNotificationCompleted(); - assertTrue("master sync should be set", mHelper.isMasterSyncAutomaticallyEnabled()); + assertTrue("master sync should be set", mAndroid.isMasterSyncEnabled()); mSyncContentResolverDelegate.setMasterSyncAutomatically(false); mSyncContentResolverDelegate.waitForLastNotificationCompleted(); - assertFalse("master sync should be unset", mHelper.isMasterSyncAutomaticallyEnabled()); + assertFalse("master sync should be unset", mAndroid.isMasterSyncEnabled()); } @SmallTest @@ -165,31 +167,31 @@ mSyncContentResolverDelegate.waitForLastNotificationCompleted(); mSyncContentResolverDelegate.setSyncAutomatically(mTestAccount, mAuthority, true); mSyncContentResolverDelegate.waitForLastNotificationCompleted(); - assertTrue("sync should be set", mHelper.isSyncEnabled(mTestAccount)); + assertTrue("sync should be set", mAndroid.isSyncEnabled(mTestAccount)); assertTrue("sync should be set for chrome app", - mHelper.isSyncEnabledForChrome(mTestAccount)); + mAndroid.isChromeSyncEnabled(mTestAccount)); // Disable sync automatically for the app mSyncContentResolverDelegate.setSyncAutomatically(mTestAccount, mAuthority, false); mSyncContentResolverDelegate.waitForLastNotificationCompleted(); - assertFalse("sync should be unset", mHelper.isSyncEnabled(mTestAccount)); + assertFalse("sync should be unset", mAndroid.isSyncEnabled(mTestAccount)); assertFalse("sync should be unset for chrome app", - mHelper.isSyncEnabledForChrome(mTestAccount)); + mAndroid.isChromeSyncEnabled(mTestAccount)); // Re-enable sync mSyncContentResolverDelegate.setSyncAutomatically(mTestAccount, mAuthority, true); mSyncContentResolverDelegate.waitForLastNotificationCompleted(); - assertTrue("sync should be re-enabled", mHelper.isSyncEnabled(mTestAccount)); + assertTrue("sync should be re-enabled", mAndroid.isSyncEnabled(mTestAccount)); assertTrue("sync should be unset for chrome app", - mHelper.isSyncEnabledForChrome(mTestAccount)); + mAndroid.isChromeSyncEnabled(mTestAccount)); // Disabled from master sync mSyncContentResolverDelegate.setMasterSyncAutomatically(false); mSyncContentResolverDelegate.waitForLastNotificationCompleted(); assertFalse("sync should be disabled due to master sync", - mHelper.isSyncEnabled(mTestAccount)); + mAndroid.isSyncEnabled(mTestAccount)); assertTrue("sync should be set for chrome app", - mHelper.isSyncEnabledForChrome(mTestAccount)); + mAndroid.isChromeSyncEnabled(mTestAccount)); } @SmallTest @@ -202,20 +204,20 @@ ThreadUtils.runOnUiThreadBlocking(new Runnable() { @Override public void run() { - mHelper.enableAndroidSync(mTestAccount); + mAndroid.enableChromeSync(mTestAccount); } }); mSyncContentResolverDelegate.waitForLastNotificationCompleted(); - assertTrue("account should be synced", mHelper.isSyncEnabled(mTestAccount)); + assertTrue("account should be synced", mAndroid.isSyncEnabled(mTestAccount)); ThreadUtils.runOnUiThreadBlocking(new Runnable() { @Override public void run() { - mHelper.disableAndroidSync(mTestAccount); + mAndroid.disableChromeSync(mTestAccount); } }); mSyncContentResolverDelegate.waitForLastNotificationCompleted(); - assertFalse("account should not be synced", mHelper.isSyncEnabled(mTestAccount)); + assertFalse("account should not be synced", mAndroid.isSyncEnabled(mTestAccount)); } @SmallTest @@ -228,35 +230,35 @@ ThreadUtils.runOnUiThreadBlocking(new Runnable() { @Override public void run() { - mHelper.enableAndroidSync(mTestAccount); + mAndroid.enableChromeSync(mTestAccount); } }); mSyncContentResolverDelegate.waitForLastNotificationCompleted(); - assertTrue("account should be synced", mHelper.isSyncEnabled(mTestAccount)); + assertTrue("account should be synced", mAndroid.isSyncEnabled(mTestAccount)); ThreadUtils.runOnUiThreadBlocking(new Runnable() { @Override public void run() { - mHelper.enableAndroidSync(mAlternateTestAccount); + mAndroid.enableChromeSync(mAlternateTestAccount); } }); mSyncContentResolverDelegate.waitForLastNotificationCompleted(); assertTrue("alternate account should be synced", - mHelper.isSyncEnabled(mAlternateTestAccount)); + mAndroid.isSyncEnabled(mAlternateTestAccount)); ThreadUtils.runOnUiThreadBlocking(new Runnable() { @Override public void run() { - mHelper.disableAndroidSync(mAlternateTestAccount); + mAndroid.disableChromeSync(mAlternateTestAccount); } }); mSyncContentResolverDelegate.waitForLastNotificationCompleted(); assertFalse("alternate account should not be synced", - mHelper.isSyncEnabled(mAlternateTestAccount)); - assertTrue("account should still be synced", mHelper.isSyncEnabled(mTestAccount)); + mAndroid.isSyncEnabled(mAlternateTestAccount)); + assertTrue("account should still be synced", mAndroid.isSyncEnabled(mTestAccount)); // Ensure we don't erroneously re-use cached data. - assertFalse("null account should not be synced", mHelper.isSyncEnabled(null)); + assertFalse("null account should not be synced", mAndroid.isSyncEnabled(null)); } @SmallTest @@ -269,11 +271,11 @@ ThreadUtils.runOnUiThreadBlocking(new Runnable() { @Override public void run() { - mHelper.enableAndroidSync(mTestAccount); + mAndroid.enableChromeSync(mTestAccount); } }); mSyncContentResolverDelegate.waitForLastNotificationCompleted(); - assertTrue("account should be synced", mHelper.isSyncEnabled(mTestAccount)); + assertTrue("account should be synced", mAndroid.isSyncEnabled(mTestAccount)); int masterSyncAutomaticallyCalls = mSyncContentResolverDelegate.mGetMasterSyncAutomaticallyCalls; @@ -281,10 +283,10 @@ int getSyncAutomaticallyAcalls = mSyncContentResolverDelegate.mGetSyncAutomaticallyCalls; // Do a bunch of reads. - mHelper.isMasterSyncAutomaticallyEnabled(); - mHelper.isSyncEnabled(); - mHelper.isSyncEnabled(mTestAccount); - mHelper.isSyncEnabledForChrome(mTestAccount); + mAndroid.isMasterSyncEnabled(); + mAndroid.isSyncEnabled(); + mAndroid.isSyncEnabled(mTestAccount); + mAndroid.isChromeSyncEnabled(mTestAccount); // Ensure values were read from cache. assertEquals(masterSyncAutomaticallyCalls, @@ -294,9 +296,9 @@ mSyncContentResolverDelegate.mGetSyncAutomaticallyCalls); // Do a bunch of reads for alternate account. - mHelper.isMasterSyncAutomaticallyEnabled(); - mHelper.isSyncEnabled(mAlternateTestAccount); - mHelper.isSyncEnabledForChrome(mAlternateTestAccount); + mAndroid.isMasterSyncEnabled(); + mAndroid.isSyncEnabled(mAlternateTestAccount); + mAndroid.isChromeSyncEnabled(mAlternateTestAccount); // Ensure master sync was cached but others are fetched once. assertEquals(masterSyncAutomaticallyCalls, @@ -311,7 +313,7 @@ public void testGetContractAuthority() throws Exception { assertEquals("The contract authority should be the package name.", getInstrumentation().getTargetContext().getPackageName(), - mHelper.getContractAuthority()); + mAndroid.getContractAuthority()); } @SmallTest @@ -356,7 +358,7 @@ @Feature({"Sync"}) public void testCachedAccountSyncSettingsDidUpdate() throws InterruptedException { // Since we're just testing the cache we disable observer notifications to prevent - // notifications to SyncStatusHelper from mutating it. + // notifications to AndroidSyncSettings from mutating it. mSyncContentResolverDelegate.disableObserverNotifications(); mCachedAccountSyncSettings.clearUpdateStatus(); @@ -418,39 +420,39 @@ @SmallTest @Feature({"Sync"}) - public void testSyncStatusHelperPostsNotifications() throws InterruptedException { + public void testAndroidSyncSettingsPostsNotifications() throws InterruptedException { // Turn on syncability. mSyncContentResolverDelegate.setMasterSyncAutomatically(true); mSyncContentResolverDelegate.waitForLastNotificationCompleted(); mSyncSettingsObserver.clearNotification(); - mHelper.isSyncEnabled(mAlternateTestAccount); + mAndroid.isSyncEnabled(mAlternateTestAccount); assertTrue("isSyncEnabled on wrongly populated cache did not trigger observers", mSyncSettingsObserver.didReceiveNotification()); mSyncSettingsObserver.clearNotification(); - mHelper.isSyncEnabled(mTestAccount); + mAndroid.isSyncEnabled(mTestAccount); assertTrue("isSyncEnabled on wrongly populated cache did not trigger observers", mSyncSettingsObserver.didReceiveNotification()); mSyncSettingsObserver.clearNotification(); - mHelper.enableAndroidSync(mTestAccount); - assertTrue("enableAndroidSync did not trigger observers", + mAndroid.enableChromeSync(mTestAccount); + assertTrue("enableChromeSync did not trigger observers", mSyncSettingsObserver.didReceiveNotification()); mSyncSettingsObserver.clearNotification(); - mHelper.enableAndroidSync(mTestAccount); - assertFalse("enableAndroidSync triggered observers", + mAndroid.enableChromeSync(mTestAccount); + assertFalse("enableChromeSync triggered observers", mSyncSettingsObserver.didReceiveNotification()); mSyncSettingsObserver.clearNotification(); - mHelper.disableAndroidSync(mTestAccount); - assertTrue("disableAndroidSync did not trigger observers", + mAndroid.disableChromeSync(mTestAccount); + assertTrue("disableChromeSync did not trigger observers", mSyncSettingsObserver.didReceiveNotification()); mSyncSettingsObserver.clearNotification(); - mHelper.disableAndroidSync(mTestAccount); - assertFalse("disableAndroidSync triggered observers", + mAndroid.disableChromeSync(mTestAccount); + assertFalse("disableChromeSync triggered observers", mSyncSettingsObserver.didReceiveNotification()); } }
diff --git a/sync/test/android/javatests/src/org/chromium/sync/test/util/MockSyncContentResolverDelegate.java b/sync/test/android/javatests/src/org/chromium/sync/test/util/MockSyncContentResolverDelegate.java index 9c8fc37..be2622c4 100644 --- a/sync/test/android/javatests/src/org/chromium/sync/test/util/MockSyncContentResolverDelegate.java +++ b/sync/test/android/javatests/src/org/chromium/sync/test/util/MockSyncContentResolverDelegate.java
@@ -13,7 +13,7 @@ import junit.framework.Assert; import org.chromium.base.ThreadUtils; -import org.chromium.sync.notifier.SyncContentResolverDelegate; +import org.chromium.sync.SyncContentResolverDelegate; import java.util.HashMap; import java.util.HashSet;
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json index 4ed436c..8f106b7 100644 --- a/testing/buildbot/chromium.chromiumos.json +++ b/testing/buildbot/chromium.chromiumos.json
@@ -88,7 +88,12 @@ "nacl_loader_unittests", "app_shell_unittests", "chromevox_tests", - "extensions_browsertests", + { + "test": "extensions_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, "skia_unittests" ] }, @@ -117,7 +122,12 @@ "device_unittests", "display_unittests", "events_unittests", - "extensions_browsertests", + { + "test": "extensions_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, "extensions_unittests", "gcm_unit_tests", "google_apis_unittests", @@ -247,7 +257,12 @@ "shards": 2 } }, - "extensions_browsertests", + { + "test": "extensions_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, "gcm_unit_tests", "skia_unittests", {
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index c7ae7dc..530c874 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -379,20 +379,10 @@ "gpu_unittests", "url_unittests", "jingle_unittests", - { - "test": "content_unittests", - "swarming": { - "can_use_on_swarming_builders": true - } - }, + "content_unittests", "device_unittests", "media_unittests", - { - "test": "net_unittests", - "swarming": { - "can_use_on_swarming_builders": true - } - }, + "net_unittests", "ppapi_unittests", "printing_unittests", "remoting_unittests", @@ -402,23 +392,12 @@ "ipc_tests", "sync_unit_tests", "skia_unittests", - { - "test": "unit_tests", - "swarming": { - "can_use_on_swarming_builders": true - } - }, + "unit_tests", "sql_unittests", "ui_base_unittests", "content_unittests", "views_unittests", - { - "test": "browser_tests", - "swarming": { - "can_use_on_swarming_builders": true, - "shards": 10 - } - }, + "browser_tests", { "test": "content_browsertests", "swarming": { @@ -740,7 +719,7 @@ "installer_util_unittests" ] }, - "CrWinClang64(asan) tester": { + "CrWinClang(asan) tester": { "gtest_tests": [ { "test": "base_unittests",
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json index 1efe19b7..a9d64db 100644 --- a/testing/buildbot/chromium.linux.json +++ b/testing/buildbot/chromium.linux.json
@@ -33,6 +33,12 @@ "cc_unittests", "chromedriver_unittests", { + "test": "components_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, + { "test": "components_unittests", "swarming": { "can_use_on_swarming_builders": true @@ -61,7 +67,12 @@ "can_use_on_swarming_builders": true } }, - "extensions_browsertests", + { + "test": "extensions_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, "extensions_unittests", "gcm_unit_tests", { @@ -229,7 +240,12 @@ "can_use_on_swarming_builders": true } }, - "extensions_browsertests", + { + "test": "extensions_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, "extensions_unittests", "gcm_unit_tests", { @@ -377,7 +393,12 @@ "can_use_on_swarming_builders": true } }, - "extensions_browsertests", + { + "test": "extensions_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, "extensions_unittests", "gcm_unit_tests", {
diff --git a/testing/buildbot/chromium.mac.json b/testing/buildbot/chromium.mac.json index 8f8a30e..f977ed6 100644 --- a/testing/buildbot/chromium.mac.json +++ b/testing/buildbot/chromium.mac.json
@@ -31,6 +31,12 @@ "cc_unittests", "chromedriver_unittests", { + "test": "components_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, + { "test": "components_unittests", "swarming": { "can_use_on_swarming_builders": true
diff --git a/testing/buildbot/chromium.webkit.json b/testing/buildbot/chromium.webkit.json index d34d31e..17cc5e9 100644 --- a/testing/buildbot/chromium.webkit.json +++ b/testing/buildbot/chromium.webkit.json
@@ -85,7 +85,12 @@ "nacl_loader_unittests", "app_shell_unittests", "chromevox_tests", - "extensions_browsertests", + { + "test": "extensions_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, "skia_unittests" ] }, @@ -171,7 +176,12 @@ "shards": 2 } }, - "extensions_browsertests", + { + "test": "extensions_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, "gcm_unit_tests", "skia_unittests", {
diff --git a/testing/buildbot/chromium.win.json b/testing/buildbot/chromium.win.json index c6c87b53..232e681 100644 --- a/testing/buildbot/chromium.win.json +++ b/testing/buildbot/chromium.win.json
@@ -23,6 +23,12 @@ "chromedriver_unittests", "chrome_elf_unittests", { + "test": "components_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, + { "test": "components_unittests", "swarming": { "can_use_on_swarming_builders": true @@ -49,7 +55,12 @@ }, "crypto_unittests", "events_unittests", - "extensions_browsertests", + { + "test": "extensions_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, "extensions_unittests", "gcm_unit_tests", "gfx_unittests", @@ -173,7 +184,12 @@ } }, "crypto_unittests", - "extensions_browsertests", + { + "test": "extensions_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, "extensions_unittests", "events_unittests", "gcm_unit_tests", @@ -311,7 +327,12 @@ "crypto_unittests", "device_unittests", "events_unittests", - "extensions_browsertests", + { + "test": "extensions_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, "extensions_unittests", "gcm_unit_tests", "gfx_unittests", @@ -454,7 +475,12 @@ "crypto_unittests", "device_unittests", "events_unittests", - "extensions_browsertests", + { + "test": "extensions_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, "extensions_unittests", "gcm_unit_tests", "gfx_unittests", @@ -594,7 +620,12 @@ }, "crypto_unittests", "events_unittests", - "extensions_browsertests", + { + "test": "extensions_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, "extensions_unittests", "gcm_unit_tests", {
diff --git a/testing/buildbot/chromium_memory_trybot.json b/testing/buildbot/chromium_memory_trybot.json index af0f169..a1b91ec 100644 --- a/testing/buildbot/chromium_memory_trybot.json +++ b/testing/buildbot/chromium_memory_trybot.json
@@ -17,6 +17,12 @@ "cacheinvalidation_unittests", "cc_unittests", { + "test": "components_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, + { "test": "components_unittests", "swarming": { "can_use_on_swarming_builders": true
diff --git a/testing/buildbot/chromium_trybot.json b/testing/buildbot/chromium_trybot.json index df5a156..87b0d23 100644 --- a/testing/buildbot/chromium_trybot.json +++ b/testing/buildbot/chromium_trybot.json
@@ -66,7 +66,12 @@ "test": "chrome_elf_unittests", "platforms": ["win"] }, - "components_browsertests", + { + "test": "components_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + } + }, { "test": "components_unittests", "swarming": { @@ -234,7 +239,10 @@ }, { "test": "extensions_browsertests", - "platforms": ["linux", "win"] + "platforms": ["linux", "win"], + "swarming": { + "can_use_on_swarming_builders": true + } }, { "test": "app_shell_unittests",
diff --git a/testing/commit_queue/config.json b/testing/commit_queue/config.json index a3142a5..c1c7eb13 100644 --- a/testing/commit_queue/config.json +++ b/testing/commit_queue/config.json
@@ -91,15 +91,12 @@ "win_chromium_x64_rel_ng": ["defaulttests"] }, "tryserver.chromium.gpu": { - "linux_gpu": ["defaulttests"], - "linux_gpu_triggered_tests": ["defaulttests"], "win_gpu": ["defaulttests"], "win_gpu_triggered_tests": ["defaulttests"] } }, "triggered": { "tryserver.chromium.gpu": { - "linux_gpu_triggered_tests": "linux_gpu", "win_gpu_triggered_tests": "win_gpu" } }
diff --git a/third_party/boringssl/boringssl.gypi b/third_party/boringssl/boringssl.gypi index b61dc77b..2691ef8 100644 --- a/third_party/boringssl/boringssl.gypi +++ b/third_party/boringssl/boringssl.gypi
@@ -353,7 +353,6 @@ 'linux-x86_64/crypto/aes/aesni-x86_64.S', 'linux-x86_64/crypto/aes/bsaes-x86_64.S', 'linux-x86_64/crypto/aes/vpaes-x86_64.S', - 'linux-x86_64/crypto/bn/modexp512-x86_64.S', 'linux-x86_64/crypto/bn/rsaz-avx2.S', 'linux-x86_64/crypto/bn/rsaz-x86_64.S', 'linux-x86_64/crypto/bn/x86_64-mont.S', @@ -388,7 +387,6 @@ 'mac-x86_64/crypto/aes/aesni-x86_64.S', 'mac-x86_64/crypto/aes/bsaes-x86_64.S', 'mac-x86_64/crypto/aes/vpaes-x86_64.S', - 'mac-x86_64/crypto/bn/modexp512-x86_64.S', 'mac-x86_64/crypto/bn/rsaz-avx2.S', 'mac-x86_64/crypto/bn/rsaz-x86_64.S', 'mac-x86_64/crypto/bn/x86_64-mont.S', @@ -423,7 +421,6 @@ 'win-x86_64/crypto/aes/aesni-x86_64.asm', 'win-x86_64/crypto/aes/bsaes-x86_64.asm', 'win-x86_64/crypto/aes/vpaes-x86_64.asm', - 'win-x86_64/crypto/bn/modexp512-x86_64.asm', 'win-x86_64/crypto/bn/rsaz-avx2.asm', 'win-x86_64/crypto/bn/rsaz-x86_64.asm', 'win-x86_64/crypto/bn/x86_64-mont.asm',
diff --git a/third_party/boringssl/linux-arm/crypto/sha/sha256-armv4.S b/third_party/boringssl/linux-arm/crypto/sha/sha256-armv4.S index 289b58ff..bf1ce4f9 100644 --- a/third_party/boringssl/linux-arm/crypto/sha/sha256-armv4.S +++ b/third_party/boringssl/linux-arm/crypto/sha/sha256-armv4.S
@@ -2690,6 +2690,6 @@ #endif .asciz "SHA256 block transform for ARMv4/NEON/ARMv8, CRYPTOGAMS by <appro@openssl.org>" .align 2 -#if __ARM_MARCH_ARCH__>=7 +#if __ARM_MAX_ARCH__>=7 .comm OPENSSL_armcap_P,4,4 #endif
diff --git a/third_party/boringssl/linux-x86_64/crypto/bn/modexp512-x86_64.S b/third_party/boringssl/linux-x86_64/crypto/bn/modexp512-x86_64.S deleted file mode 100644 index e49a2cbf..0000000 --- a/third_party/boringssl/linux-x86_64/crypto/bn/modexp512-x86_64.S +++ /dev/null
@@ -1,1776 +0,0 @@ -#if defined(__x86_64__) -.text - -.type MULADD_128x512,@function -.align 16 -MULADD_128x512: - movq 0(%rsi),%rax - mulq %rbp - addq %rax,%r8 - adcq $0,%rdx - movq %r8,0(%rcx) - movq %rdx,%rbx - - movq 8(%rsi),%rax - mulq %rbp - addq %rax,%r9 - adcq $0,%rdx - addq %rbx,%r9 - adcq $0,%rdx - movq %rdx,%rbx - - movq 16(%rsi),%rax - mulq %rbp - addq %rax,%r10 - adcq $0,%rdx - addq %rbx,%r10 - adcq $0,%rdx - movq %rdx,%rbx - - movq 24(%rsi),%rax - mulq %rbp - addq %rax,%r11 - adcq $0,%rdx - addq %rbx,%r11 - adcq $0,%rdx - movq %rdx,%rbx - - movq 32(%rsi),%rax - mulq %rbp - addq %rax,%r12 - adcq $0,%rdx - addq %rbx,%r12 - adcq $0,%rdx - movq %rdx,%rbx - - movq 40(%rsi),%rax - mulq %rbp - addq %rax,%r13 - adcq $0,%rdx - addq %rbx,%r13 - adcq $0,%rdx - movq %rdx,%rbx - - movq 48(%rsi),%rax - mulq %rbp - addq %rax,%r14 - adcq $0,%rdx - addq %rbx,%r14 - adcq $0,%rdx - movq %rdx,%rbx - - movq 56(%rsi),%rax - mulq %rbp - addq %rax,%r15 - adcq $0,%rdx - addq %rbx,%r15 - adcq $0,%rdx - movq %rdx,%r8 - movq 8(%rdi),%rbp - movq 0(%rsi),%rax - mulq %rbp - addq %rax,%r9 - adcq $0,%rdx - movq %r9,8(%rcx) - movq %rdx,%rbx - - movq 8(%rsi),%rax - mulq %rbp - addq %rax,%r10 - adcq $0,%rdx - addq %rbx,%r10 - adcq $0,%rdx - movq %rdx,%rbx - - movq 16(%rsi),%rax - mulq %rbp - addq %rax,%r11 - adcq $0,%rdx - addq %rbx,%r11 - adcq $0,%rdx - movq %rdx,%rbx - - movq 24(%rsi),%rax - mulq %rbp - addq %rax,%r12 - adcq $0,%rdx - addq %rbx,%r12 - adcq $0,%rdx - movq %rdx,%rbx - - movq 32(%rsi),%rax - mulq %rbp - addq %rax,%r13 - adcq $0,%rdx - addq %rbx,%r13 - adcq $0,%rdx - movq %rdx,%rbx - - movq 40(%rsi),%rax - mulq %rbp - addq %rax,%r14 - adcq $0,%rdx - addq %rbx,%r14 - adcq $0,%rdx - movq %rdx,%rbx - - movq 48(%rsi),%rax - mulq %rbp - addq %rax,%r15 - adcq $0,%rdx - addq %rbx,%r15 - adcq $0,%rdx - movq %rdx,%rbx - - movq 56(%rsi),%rax - mulq %rbp - addq %rax,%r8 - adcq $0,%rdx - addq %rbx,%r8 - adcq $0,%rdx - movq %rdx,%r9 - .byte 0xf3,0xc3 -.size MULADD_128x512,.-MULADD_128x512 -.type mont_reduce,@function -.align 16 -mont_reduce: - leaq 192(%rsp),%rdi - movq 32(%rsp),%rsi - addq $576,%rsi - leaq 520(%rsp),%rcx - - movq 96(%rcx),%rbp - movq 0(%rsi),%rax - mulq %rbp - movq (%rcx),%r8 - addq %rax,%r8 - adcq $0,%rdx - movq %r8,0(%rdi) - movq %rdx,%rbx - - movq 8(%rsi),%rax - mulq %rbp - movq 8(%rcx),%r9 - addq %rax,%r9 - adcq $0,%rdx - addq %rbx,%r9 - adcq $0,%rdx - movq %rdx,%rbx - - movq 16(%rsi),%rax - mulq %rbp - movq 16(%rcx),%r10 - addq %rax,%r10 - adcq $0,%rdx - addq %rbx,%r10 - adcq $0,%rdx - movq %rdx,%rbx - - movq 24(%rsi),%rax - mulq %rbp - movq 24(%rcx),%r11 - addq %rax,%r11 - adcq $0,%rdx - addq %rbx,%r11 - adcq $0,%rdx - movq %rdx,%rbx - - movq 32(%rsi),%rax - mulq %rbp - movq 32(%rcx),%r12 - addq %rax,%r12 - adcq $0,%rdx - addq %rbx,%r12 - adcq $0,%rdx - movq %rdx,%rbx - - movq 40(%rsi),%rax - mulq %rbp - movq 40(%rcx),%r13 - addq %rax,%r13 - adcq $0,%rdx - addq %rbx,%r13 - adcq $0,%rdx - movq %rdx,%rbx - - movq 48(%rsi),%rax - mulq %rbp - movq 48(%rcx),%r14 - addq %rax,%r14 - adcq $0,%rdx - addq %rbx,%r14 - adcq $0,%rdx - movq %rdx,%rbx - - movq 56(%rsi),%rax - mulq %rbp - movq 56(%rcx),%r15 - addq %rax,%r15 - adcq $0,%rdx - addq %rbx,%r15 - adcq $0,%rdx - movq %rdx,%r8 - movq 104(%rcx),%rbp - movq 0(%rsi),%rax - mulq %rbp - addq %rax,%r9 - adcq $0,%rdx - movq %r9,8(%rdi) - movq %rdx,%rbx - - movq 8(%rsi),%rax - mulq %rbp - addq %rax,%r10 - adcq $0,%rdx - addq %rbx,%r10 - adcq $0,%rdx - movq %rdx,%rbx - - movq 16(%rsi),%rax - mulq %rbp - addq %rax,%r11 - adcq $0,%rdx - addq %rbx,%r11 - adcq $0,%rdx - movq %rdx,%rbx - - movq 24(%rsi),%rax - mulq %rbp - addq %rax,%r12 - adcq $0,%rdx - addq %rbx,%r12 - adcq $0,%rdx - movq %rdx,%rbx - - movq 32(%rsi),%rax - mulq %rbp - addq %rax,%r13 - adcq $0,%rdx - addq %rbx,%r13 - adcq $0,%rdx - movq %rdx,%rbx - - movq 40(%rsi),%rax - mulq %rbp - addq %rax,%r14 - adcq $0,%rdx - addq %rbx,%r14 - adcq $0,%rdx - movq %rdx,%rbx - - movq 48(%rsi),%rax - mulq %rbp - addq %rax,%r15 - adcq $0,%rdx - addq %rbx,%r15 - adcq $0,%rdx - movq %rdx,%rbx - - movq 56(%rsi),%rax - mulq %rbp - addq %rax,%r8 - adcq $0,%rdx - addq %rbx,%r8 - adcq $0,%rdx - movq %rdx,%r9 - movq 112(%rcx),%rbp - movq 0(%rsi),%rax - mulq %rbp - addq %rax,%r10 - adcq $0,%rdx - movq %r10,16(%rdi) - movq %rdx,%rbx - - movq 8(%rsi),%rax - mulq %rbp - addq %rax,%r11 - adcq $0,%rdx - addq %rbx,%r11 - adcq $0,%rdx - movq %rdx,%rbx - - movq 16(%rsi),%rax - mulq %rbp - addq %rax,%r12 - adcq $0,%rdx - addq %rbx,%r12 - adcq $0,%rdx - movq %rdx,%rbx - - movq 24(%rsi),%rax - mulq %rbp - addq %rax,%r13 - adcq $0,%rdx - addq %rbx,%r13 - adcq $0,%rdx - movq %rdx,%rbx - - movq 32(%rsi),%rax - mulq %rbp - addq %rax,%r14 - adcq $0,%rdx - addq %rbx,%r14 - adcq $0,%rdx - movq %rdx,%rbx - - movq 40(%rsi),%rax - mulq %rbp - addq %rax,%r15 - adcq $0,%rdx - addq %rbx,%r15 - adcq $0,%rdx - movq %rdx,%rbx - - movq 48(%rsi),%rax - mulq %rbp - addq %rax,%r8 - adcq $0,%rdx - addq %rbx,%r8 - adcq $0,%rdx - movq %rdx,%rbx - - movq 56(%rsi),%rax - mulq %rbp - addq %rax,%r9 - adcq $0,%rdx - addq %rbx,%r9 - adcq $0,%rdx - movq %rdx,%r10 - movq 120(%rcx),%rbp - movq 0(%rsi),%rax - mulq %rbp - addq %rax,%r11 - adcq $0,%rdx - movq %r11,24(%rdi) - movq %rdx,%rbx - - movq 8(%rsi),%rax - mulq %rbp - addq %rax,%r12 - adcq $0,%rdx - addq %rbx,%r12 - adcq $0,%rdx - movq %rdx,%rbx - - movq 16(%rsi),%rax - mulq %rbp - addq %rax,%r13 - adcq $0,%rdx - addq %rbx,%r13 - adcq $0,%rdx - movq %rdx,%rbx - - movq 24(%rsi),%rax - mulq %rbp - addq %rax,%r14 - adcq $0,%rdx - addq %rbx,%r14 - adcq $0,%rdx - movq %rdx,%rbx - - movq 32(%rsi),%rax - mulq %rbp - addq %rax,%r15 - adcq $0,%rdx - addq %rbx,%r15 - adcq $0,%rdx - movq %rdx,%rbx - - movq 40(%rsi),%rax - mulq %rbp - addq %rax,%r8 - adcq $0,%rdx - addq %rbx,%r8 - adcq $0,%rdx - movq %rdx,%rbx - - movq 48(%rsi),%rax - mulq %rbp - addq %rax,%r9 - adcq $0,%rdx - addq %rbx,%r9 - adcq $0,%rdx - movq %rdx,%rbx - - movq 56(%rsi),%rax - mulq %rbp - addq %rax,%r10 - adcq $0,%rdx - addq %rbx,%r10 - adcq $0,%rdx - movq %rdx,%r11 - xorq %rax,%rax - - addq 64(%rcx),%r8 - adcq 72(%rcx),%r9 - adcq 80(%rcx),%r10 - adcq 88(%rcx),%r11 - adcq $0,%rax - - - - - movq %r8,64(%rdi) - movq %r9,72(%rdi) - movq %r10,%rbp - movq %r11,88(%rdi) - - movq %rax,384(%rsp) - - movq 0(%rdi),%r8 - movq 8(%rdi),%r9 - movq 16(%rdi),%r10 - movq 24(%rdi),%r11 - - - - - - - - - addq $80,%rdi - - addq $64,%rsi - leaq 296(%rsp),%rcx - - call MULADD_128x512 - - movq 384(%rsp),%rax - - - addq -16(%rdi),%r8 - adcq -8(%rdi),%r9 - movq %r8,64(%rcx) - movq %r9,72(%rcx) - - adcq %rax,%rax - movq %rax,384(%rsp) - - leaq 192(%rsp),%rdi - addq $64,%rsi - - - - - - movq (%rsi),%r8 - movq 8(%rsi),%rbx - - movq (%rcx),%rax - mulq %r8 - movq %rax,%rbp - movq %rdx,%r9 - - movq 8(%rcx),%rax - mulq %r8 - addq %rax,%r9 - - movq (%rcx),%rax - mulq %rbx - addq %rax,%r9 - - movq %r9,8(%rdi) - - - subq $192,%rsi - - movq (%rcx),%r8 - movq 8(%rcx),%r9 - - call MULADD_128x512 - - - - - movq 0(%rsi),%rax - movq 8(%rsi),%rbx - movq 16(%rsi),%rdi - movq 24(%rsi),%rdx - - - movq 384(%rsp),%rbp - - addq 64(%rcx),%r8 - adcq 72(%rcx),%r9 - - - adcq %rbp,%rbp - - - - shlq $3,%rbp - movq 32(%rsp),%rcx - addq %rcx,%rbp - - - xorq %rsi,%rsi - - addq 0(%rbp),%r10 - adcq 64(%rbp),%r11 - adcq 128(%rbp),%r12 - adcq 192(%rbp),%r13 - adcq 256(%rbp),%r14 - adcq 320(%rbp),%r15 - adcq 384(%rbp),%r8 - adcq 448(%rbp),%r9 - - - - sbbq $0,%rsi - - - andq %rsi,%rax - andq %rsi,%rbx - andq %rsi,%rdi - andq %rsi,%rdx - - movq $1,%rbp - subq %rax,%r10 - sbbq %rbx,%r11 - sbbq %rdi,%r12 - sbbq %rdx,%r13 - - - - - sbbq $0,%rbp - - - - addq $512,%rcx - movq 32(%rcx),%rax - movq 40(%rcx),%rbx - movq 48(%rcx),%rdi - movq 56(%rcx),%rdx - - - - andq %rsi,%rax - andq %rsi,%rbx - andq %rsi,%rdi - andq %rsi,%rdx - - - - subq $1,%rbp - - sbbq %rax,%r14 - sbbq %rbx,%r15 - sbbq %rdi,%r8 - sbbq %rdx,%r9 - - - - movq 144(%rsp),%rsi - movq %r10,0(%rsi) - movq %r11,8(%rsi) - movq %r12,16(%rsi) - movq %r13,24(%rsi) - movq %r14,32(%rsi) - movq %r15,40(%rsi) - movq %r8,48(%rsi) - movq %r9,56(%rsi) - - .byte 0xf3,0xc3 -.size mont_reduce,.-mont_reduce -.type mont_mul_a3b,@function -.align 16 -mont_mul_a3b: - - - - - movq 0(%rdi),%rbp - - movq %r10,%rax - mulq %rbp - movq %rax,520(%rsp) - movq %rdx,%r10 - movq %r11,%rax - mulq %rbp - addq %rax,%r10 - adcq $0,%rdx - movq %rdx,%r11 - movq %r12,%rax - mulq %rbp - addq %rax,%r11 - adcq $0,%rdx - movq %rdx,%r12 - movq %r13,%rax - mulq %rbp - addq %rax,%r12 - adcq $0,%rdx - movq %rdx,%r13 - movq %r14,%rax - mulq %rbp - addq %rax,%r13 - adcq $0,%rdx - movq %rdx,%r14 - movq %r15,%rax - mulq %rbp - addq %rax,%r14 - adcq $0,%rdx - movq %rdx,%r15 - movq %r8,%rax - mulq %rbp - addq %rax,%r15 - adcq $0,%rdx - movq %rdx,%r8 - movq %r9,%rax - mulq %rbp - addq %rax,%r8 - adcq $0,%rdx - movq %rdx,%r9 - movq 8(%rdi),%rbp - movq 0(%rsi),%rax - mulq %rbp - addq %rax,%r10 - adcq $0,%rdx - movq %r10,528(%rsp) - movq %rdx,%rbx - - movq 8(%rsi),%rax - mulq %rbp - addq %rax,%r11 - adcq $0,%rdx - addq %rbx,%r11 - adcq $0,%rdx - movq %rdx,%rbx - - movq 16(%rsi),%rax - mulq %rbp - addq %rax,%r12 - adcq $0,%rdx - addq %rbx,%r12 - adcq $0,%rdx - movq %rdx,%rbx - - movq 24(%rsi),%rax - mulq %rbp - addq %rax,%r13 - adcq $0,%rdx - addq %rbx,%r13 - adcq $0,%rdx - movq %rdx,%rbx - - movq 32(%rsi),%rax - mulq %rbp - addq %rax,%r14 - adcq $0,%rdx - addq %rbx,%r14 - adcq $0,%rdx - movq %rdx,%rbx - - movq 40(%rsi),%rax - mulq %rbp - addq %rax,%r15 - adcq $0,%rdx - addq %rbx,%r15 - adcq $0,%rdx - movq %rdx,%rbx - - movq 48(%rsi),%rax - mulq %rbp - addq %rax,%r8 - adcq $0,%rdx - addq %rbx,%r8 - adcq $0,%rdx - movq %rdx,%rbx - - movq 56(%rsi),%rax - mulq %rbp - addq %rax,%r9 - adcq $0,%rdx - addq %rbx,%r9 - adcq $0,%rdx - movq %rdx,%r10 - movq 16(%rdi),%rbp - movq 0(%rsi),%rax - mulq %rbp - addq %rax,%r11 - adcq $0,%rdx - movq %r11,536(%rsp) - movq %rdx,%rbx - - movq 8(%rsi),%rax - mulq %rbp - addq %rax,%r12 - adcq $0,%rdx - addq %rbx,%r12 - adcq $0,%rdx - movq %rdx,%rbx - - movq 16(%rsi),%rax - mulq %rbp - addq %rax,%r13 - adcq $0,%rdx - addq %rbx,%r13 - adcq $0,%rdx - movq %rdx,%rbx - - movq 24(%rsi),%rax - mulq %rbp - addq %rax,%r14 - adcq $0,%rdx - addq %rbx,%r14 - adcq $0,%rdx - movq %rdx,%rbx - - movq 32(%rsi),%rax - mulq %rbp - addq %rax,%r15 - adcq $0,%rdx - addq %rbx,%r15 - adcq $0,%rdx - movq %rdx,%rbx - - movq 40(%rsi),%rax - mulq %rbp - addq %rax,%r8 - adcq $0,%rdx - addq %rbx,%r8 - adcq $0,%rdx - movq %rdx,%rbx - - movq 48(%rsi),%rax - mulq %rbp - addq %rax,%r9 - adcq $0,%rdx - addq %rbx,%r9 - adcq $0,%rdx - movq %rdx,%rbx - - movq 56(%rsi),%rax - mulq %rbp - addq %rax,%r10 - adcq $0,%rdx - addq %rbx,%r10 - adcq $0,%rdx - movq %rdx,%r11 - movq 24(%rdi),%rbp - movq 0(%rsi),%rax - mulq %rbp - addq %rax,%r12 - adcq $0,%rdx - movq %r12,544(%rsp) - movq %rdx,%rbx - - movq 8(%rsi),%rax - mulq %rbp - addq %rax,%r13 - adcq $0,%rdx - addq %rbx,%r13 - adcq $0,%rdx - movq %rdx,%rbx - - movq 16(%rsi),%rax - mulq %rbp - addq %rax,%r14 - adcq $0,%rdx - addq %rbx,%r14 - adcq $0,%rdx - movq %rdx,%rbx - - movq 24(%rsi),%rax - mulq %rbp - addq %rax,%r15 - adcq $0,%rdx - addq %rbx,%r15 - adcq $0,%rdx - movq %rdx,%rbx - - movq 32(%rsi),%rax - mulq %rbp - addq %rax,%r8 - adcq $0,%rdx - addq %rbx,%r8 - adcq $0,%rdx - movq %rdx,%rbx - - movq 40(%rsi),%rax - mulq %rbp - addq %rax,%r9 - adcq $0,%rdx - addq %rbx,%r9 - adcq $0,%rdx - movq %rdx,%rbx - - movq 48(%rsi),%rax - mulq %rbp - addq %rax,%r10 - adcq $0,%rdx - addq %rbx,%r10 - adcq $0,%rdx - movq %rdx,%rbx - - movq 56(%rsi),%rax - mulq %rbp - addq %rax,%r11 - adcq $0,%rdx - addq %rbx,%r11 - adcq $0,%rdx - movq %rdx,%r12 - movq 32(%rdi),%rbp - movq 0(%rsi),%rax - mulq %rbp - addq %rax,%r13 - adcq $0,%rdx - movq %r13,552(%rsp) - movq %rdx,%rbx - - movq 8(%rsi),%rax - mulq %rbp - addq %rax,%r14 - adcq $0,%rdx - addq %rbx,%r14 - adcq $0,%rdx - movq %rdx,%rbx - - movq 16(%rsi),%rax - mulq %rbp - addq %rax,%r15 - adcq $0,%rdx - addq %rbx,%r15 - adcq $0,%rdx - movq %rdx,%rbx - - movq 24(%rsi),%rax - mulq %rbp - addq %rax,%r8 - adcq $0,%rdx - addq %rbx,%r8 - adcq $0,%rdx - movq %rdx,%rbx - - movq 32(%rsi),%rax - mulq %rbp - addq %rax,%r9 - adcq $0,%rdx - addq %rbx,%r9 - adcq $0,%rdx - movq %rdx,%rbx - - movq 40(%rsi),%rax - mulq %rbp - addq %rax,%r10 - adcq $0,%rdx - addq %rbx,%r10 - adcq $0,%rdx - movq %rdx,%rbx - - movq 48(%rsi),%rax - mulq %rbp - addq %rax,%r11 - adcq $0,%rdx - addq %rbx,%r11 - adcq $0,%rdx - movq %rdx,%rbx - - movq 56(%rsi),%rax - mulq %rbp - addq %rax,%r12 - adcq $0,%rdx - addq %rbx,%r12 - adcq $0,%rdx - movq %rdx,%r13 - movq 40(%rdi),%rbp - movq 0(%rsi),%rax - mulq %rbp - addq %rax,%r14 - adcq $0,%rdx - movq %r14,560(%rsp) - movq %rdx,%rbx - - movq 8(%rsi),%rax - mulq %rbp - addq %rax,%r15 - adcq $0,%rdx - addq %rbx,%r15 - adcq $0,%rdx - movq %rdx,%rbx - - movq 16(%rsi),%rax - mulq %rbp - addq %rax,%r8 - adcq $0,%rdx - addq %rbx,%r8 - adcq $0,%rdx - movq %rdx,%rbx - - movq 24(%rsi),%rax - mulq %rbp - addq %rax,%r9 - adcq $0,%rdx - addq %rbx,%r9 - adcq $0,%rdx - movq %rdx,%rbx - - movq 32(%rsi),%rax - mulq %rbp - addq %rax,%r10 - adcq $0,%rdx - addq %rbx,%r10 - adcq $0,%rdx - movq %rdx,%rbx - - movq 40(%rsi),%rax - mulq %rbp - addq %rax,%r11 - adcq $0,%rdx - addq %rbx,%r11 - adcq $0,%rdx - movq %rdx,%rbx - - movq 48(%rsi),%rax - mulq %rbp - addq %rax,%r12 - adcq $0,%rdx - addq %rbx,%r12 - adcq $0,%rdx - movq %rdx,%rbx - - movq 56(%rsi),%rax - mulq %rbp - addq %rax,%r13 - adcq $0,%rdx - addq %rbx,%r13 - adcq $0,%rdx - movq %rdx,%r14 - movq 48(%rdi),%rbp - movq 0(%rsi),%rax - mulq %rbp - addq %rax,%r15 - adcq $0,%rdx - movq %r15,568(%rsp) - movq %rdx,%rbx - - movq 8(%rsi),%rax - mulq %rbp - addq %rax,%r8 - adcq $0,%rdx - addq %rbx,%r8 - adcq $0,%rdx - movq %rdx,%rbx - - movq 16(%rsi),%rax - mulq %rbp - addq %rax,%r9 - adcq $0,%rdx - addq %rbx,%r9 - adcq $0,%rdx - movq %rdx,%rbx - - movq 24(%rsi),%rax - mulq %rbp - addq %rax,%r10 - adcq $0,%rdx - addq %rbx,%r10 - adcq $0,%rdx - movq %rdx,%rbx - - movq 32(%rsi),%rax - mulq %rbp - addq %rax,%r11 - adcq $0,%rdx - addq %rbx,%r11 - adcq $0,%rdx - movq %rdx,%rbx - - movq 40(%rsi),%rax - mulq %rbp - addq %rax,%r12 - adcq $0,%rdx - addq %rbx,%r12 - adcq $0,%rdx - movq %rdx,%rbx - - movq 48(%rsi),%rax - mulq %rbp - addq %rax,%r13 - adcq $0,%rdx - addq %rbx,%r13 - adcq $0,%rdx - movq %rdx,%rbx - - movq 56(%rsi),%rax - mulq %rbp - addq %rax,%r14 - adcq $0,%rdx - addq %rbx,%r14 - adcq $0,%rdx - movq %rdx,%r15 - movq 56(%rdi),%rbp - movq 0(%rsi),%rax - mulq %rbp - addq %rax,%r8 - adcq $0,%rdx - movq %r8,576(%rsp) - movq %rdx,%rbx - - movq 8(%rsi),%rax - mulq %rbp - addq %rax,%r9 - adcq $0,%rdx - addq %rbx,%r9 - adcq $0,%rdx - movq %rdx,%rbx - - movq 16(%rsi),%rax - mulq %rbp - addq %rax,%r10 - adcq $0,%rdx - addq %rbx,%r10 - adcq $0,%rdx - movq %rdx,%rbx - - movq 24(%rsi),%rax - mulq %rbp - addq %rax,%r11 - adcq $0,%rdx - addq %rbx,%r11 - adcq $0,%rdx - movq %rdx,%rbx - - movq 32(%rsi),%rax - mulq %rbp - addq %rax,%r12 - adcq $0,%rdx - addq %rbx,%r12 - adcq $0,%rdx - movq %rdx,%rbx - - movq 40(%rsi),%rax - mulq %rbp - addq %rax,%r13 - adcq $0,%rdx - addq %rbx,%r13 - adcq $0,%rdx - movq %rdx,%rbx - - movq 48(%rsi),%rax - mulq %rbp - addq %rax,%r14 - adcq $0,%rdx - addq %rbx,%r14 - adcq $0,%rdx - movq %rdx,%rbx - - movq 56(%rsi),%rax - mulq %rbp - addq %rax,%r15 - adcq $0,%rdx - addq %rbx,%r15 - adcq $0,%rdx - movq %rdx,%r8 - movq %r9,584(%rsp) - movq %r10,592(%rsp) - movq %r11,600(%rsp) - movq %r12,608(%rsp) - movq %r13,616(%rsp) - movq %r14,624(%rsp) - movq %r15,632(%rsp) - movq %r8,640(%rsp) - - - - - - jmp mont_reduce - - -.size mont_mul_a3b,.-mont_mul_a3b -.type sqr_reduce,@function -.align 16 -sqr_reduce: - movq 16(%rsp),%rcx - - - - movq %r10,%rbx - - movq %r11,%rax - mulq %rbx - movq %rax,528(%rsp) - movq %rdx,%r10 - movq %r12,%rax - mulq %rbx - addq %rax,%r10 - adcq $0,%rdx - movq %rdx,%r11 - movq %r13,%rax - mulq %rbx - addq %rax,%r11 - adcq $0,%rdx - movq %rdx,%r12 - movq %r14,%rax - mulq %rbx - addq %rax,%r12 - adcq $0,%rdx - movq %rdx,%r13 - movq %r15,%rax - mulq %rbx - addq %rax,%r13 - adcq $0,%rdx - movq %rdx,%r14 - movq %r8,%rax - mulq %rbx - addq %rax,%r14 - adcq $0,%rdx - movq %rdx,%r15 - movq %r9,%rax - mulq %rbx - addq %rax,%r15 - adcq $0,%rdx - movq %rdx,%rsi - - movq %r10,536(%rsp) - - - - - - movq 8(%rcx),%rbx - - movq 16(%rcx),%rax - mulq %rbx - addq %rax,%r11 - adcq $0,%rdx - movq %r11,544(%rsp) - - movq %rdx,%r10 - movq 24(%rcx),%rax - mulq %rbx - addq %rax,%r12 - adcq $0,%rdx - addq %r10,%r12 - adcq $0,%rdx - movq %r12,552(%rsp) - - movq %rdx,%r10 - movq 32(%rcx),%rax - mulq %rbx - addq %rax,%r13 - adcq $0,%rdx - addq %r10,%r13 - adcq $0,%rdx - - movq %rdx,%r10 - movq 40(%rcx),%rax - mulq %rbx - addq %rax,%r14 - adcq $0,%rdx - addq %r10,%r14 - adcq $0,%rdx - - movq %rdx,%r10 - movq %r8,%rax - mulq %rbx - addq %rax,%r15 - adcq $0,%rdx - addq %r10,%r15 - adcq $0,%rdx - - movq %rdx,%r10 - movq %r9,%rax - mulq %rbx - addq %rax,%rsi - adcq $0,%rdx - addq %r10,%rsi - adcq $0,%rdx - - movq %rdx,%r11 - - - - - movq 16(%rcx),%rbx - - movq 24(%rcx),%rax - mulq %rbx - addq %rax,%r13 - adcq $0,%rdx - movq %r13,560(%rsp) - - movq %rdx,%r10 - movq 32(%rcx),%rax - mulq %rbx - addq %rax,%r14 - adcq $0,%rdx - addq %r10,%r14 - adcq $0,%rdx - movq %r14,568(%rsp) - - movq %rdx,%r10 - movq 40(%rcx),%rax - mulq %rbx - addq %rax,%r15 - adcq $0,%rdx - addq %r10,%r15 - adcq $0,%rdx - - movq %rdx,%r10 - movq %r8,%rax - mulq %rbx - addq %rax,%rsi - adcq $0,%rdx - addq %r10,%rsi - adcq $0,%rdx - - movq %rdx,%r10 - movq %r9,%rax - mulq %rbx - addq %rax,%r11 - adcq $0,%rdx - addq %r10,%r11 - adcq $0,%rdx - - movq %rdx,%r12 - - - - - - movq 24(%rcx),%rbx - - movq 32(%rcx),%rax - mulq %rbx - addq %rax,%r15 - adcq $0,%rdx - movq %r15,576(%rsp) - - movq %rdx,%r10 - movq 40(%rcx),%rax - mulq %rbx - addq %rax,%rsi - adcq $0,%rdx - addq %r10,%rsi - adcq $0,%rdx - movq %rsi,584(%rsp) - - movq %rdx,%r10 - movq %r8,%rax - mulq %rbx - addq %rax,%r11 - adcq $0,%rdx - addq %r10,%r11 - adcq $0,%rdx - - movq %rdx,%r10 - movq %r9,%rax - mulq %rbx - addq %rax,%r12 - adcq $0,%rdx - addq %r10,%r12 - adcq $0,%rdx - - movq %rdx,%r15 - - - - - movq 32(%rcx),%rbx - - movq 40(%rcx),%rax - mulq %rbx - addq %rax,%r11 - adcq $0,%rdx - movq %r11,592(%rsp) - - movq %rdx,%r10 - movq %r8,%rax - mulq %rbx - addq %rax,%r12 - adcq $0,%rdx - addq %r10,%r12 - adcq $0,%rdx - movq %r12,600(%rsp) - - movq %rdx,%r10 - movq %r9,%rax - mulq %rbx - addq %rax,%r15 - adcq $0,%rdx - addq %r10,%r15 - adcq $0,%rdx - - movq %rdx,%r11 - - - - - movq 40(%rcx),%rbx - - movq %r8,%rax - mulq %rbx - addq %rax,%r15 - adcq $0,%rdx - movq %r15,608(%rsp) - - movq %rdx,%r10 - movq %r9,%rax - mulq %rbx - addq %rax,%r11 - adcq $0,%rdx - addq %r10,%r11 - adcq $0,%rdx - movq %r11,616(%rsp) - - movq %rdx,%r12 - - - - - movq %r8,%rbx - - movq %r9,%rax - mulq %rbx - addq %rax,%r12 - adcq $0,%rdx - movq %r12,624(%rsp) - - movq %rdx,632(%rsp) - - - movq 528(%rsp),%r10 - movq 536(%rsp),%r11 - movq 544(%rsp),%r12 - movq 552(%rsp),%r13 - movq 560(%rsp),%r14 - movq 568(%rsp),%r15 - - movq 24(%rcx),%rax - mulq %rax - movq %rax,%rdi - movq %rdx,%r8 - - addq %r10,%r10 - adcq %r11,%r11 - adcq %r12,%r12 - adcq %r13,%r13 - adcq %r14,%r14 - adcq %r15,%r15 - adcq $0,%r8 - - movq 0(%rcx),%rax - mulq %rax - movq %rax,520(%rsp) - movq %rdx,%rbx - - movq 8(%rcx),%rax - mulq %rax - - addq %rbx,%r10 - adcq %rax,%r11 - adcq $0,%rdx - - movq %rdx,%rbx - movq %r10,528(%rsp) - movq %r11,536(%rsp) - - movq 16(%rcx),%rax - mulq %rax - - addq %rbx,%r12 - adcq %rax,%r13 - adcq $0,%rdx - - movq %rdx,%rbx - - movq %r12,544(%rsp) - movq %r13,552(%rsp) - - xorq %rbp,%rbp - addq %rbx,%r14 - adcq %rdi,%r15 - adcq $0,%rbp - - movq %r14,560(%rsp) - movq %r15,568(%rsp) - - - - - movq 576(%rsp),%r10 - movq 584(%rsp),%r11 - movq 592(%rsp),%r12 - movq 600(%rsp),%r13 - movq 608(%rsp),%r14 - movq 616(%rsp),%r15 - movq 624(%rsp),%rdi - movq 632(%rsp),%rsi - - movq %r9,%rax - mulq %rax - movq %rax,%r9 - movq %rdx,%rbx - - addq %r10,%r10 - adcq %r11,%r11 - adcq %r12,%r12 - adcq %r13,%r13 - adcq %r14,%r14 - adcq %r15,%r15 - adcq %rdi,%rdi - adcq %rsi,%rsi - adcq $0,%rbx - - addq %rbp,%r10 - - movq 32(%rcx),%rax - mulq %rax - - addq %r8,%r10 - adcq %rax,%r11 - adcq $0,%rdx - - movq %rdx,%rbp - - movq %r10,576(%rsp) - movq %r11,584(%rsp) - - movq 40(%rcx),%rax - mulq %rax - - addq %rbp,%r12 - adcq %rax,%r13 - adcq $0,%rdx - - movq %rdx,%rbp - - movq %r12,592(%rsp) - movq %r13,600(%rsp) - - movq 48(%rcx),%rax - mulq %rax - - addq %rbp,%r14 - adcq %rax,%r15 - adcq $0,%rdx - - movq %r14,608(%rsp) - movq %r15,616(%rsp) - - addq %rdx,%rdi - adcq %r9,%rsi - adcq $0,%rbx - - movq %rdi,624(%rsp) - movq %rsi,632(%rsp) - movq %rbx,640(%rsp) - - jmp mont_reduce - - -.size sqr_reduce,.-sqr_reduce -.globl mod_exp_512 -.hidden mod_exp_512 -.type mod_exp_512,@function -mod_exp_512: - pushq %rbp - pushq %rbx - pushq %r12 - pushq %r13 - pushq %r14 - pushq %r15 - - - movq %rsp,%r8 - subq $2688,%rsp - andq $-64,%rsp - - - movq %r8,0(%rsp) - movq %rdi,8(%rsp) - movq %rsi,16(%rsp) - movq %rcx,24(%rsp) -.Lbody: - - - - pxor %xmm4,%xmm4 - movdqu 0(%rsi),%xmm0 - movdqu 16(%rsi),%xmm1 - movdqu 32(%rsi),%xmm2 - movdqu 48(%rsi),%xmm3 - movdqa %xmm4,512(%rsp) - movdqa %xmm4,528(%rsp) - movdqa %xmm4,608(%rsp) - movdqa %xmm4,624(%rsp) - movdqa %xmm0,544(%rsp) - movdqa %xmm1,560(%rsp) - movdqa %xmm2,576(%rsp) - movdqa %xmm3,592(%rsp) - - - movdqu 0(%rdx),%xmm0 - movdqu 16(%rdx),%xmm1 - movdqu 32(%rdx),%xmm2 - movdqu 48(%rdx),%xmm3 - - leaq 384(%rsp),%rbx - movq %rbx,136(%rsp) - call mont_reduce - - - leaq 448(%rsp),%rcx - xorq %rax,%rax - movq %rax,0(%rcx) - movq %rax,8(%rcx) - movq %rax,24(%rcx) - movq %rax,32(%rcx) - movq %rax,40(%rcx) - movq %rax,48(%rcx) - movq %rax,56(%rcx) - movq %rax,128(%rsp) - movq $1,16(%rcx) - - leaq 640(%rsp),%rbp - movq %rcx,%rsi - movq %rbp,%rdi - movq $8,%rax -loop_0: - movq (%rcx),%rbx - movw %bx,(%rdi) - shrq $16,%rbx - movw %bx,64(%rdi) - shrq $16,%rbx - movw %bx,128(%rdi) - shrq $16,%rbx - movw %bx,192(%rdi) - leaq 8(%rcx),%rcx - leaq 256(%rdi),%rdi - decq %rax - jnz loop_0 - movq $31,%rax - movq %rax,32(%rsp) - movq %rbp,40(%rsp) - - movq %rsi,136(%rsp) - movq 0(%rsi),%r10 - movq 8(%rsi),%r11 - movq 16(%rsi),%r12 - movq 24(%rsi),%r13 - movq 32(%rsi),%r14 - movq 40(%rsi),%r15 - movq 48(%rsi),%r8 - movq 56(%rsi),%r9 -init_loop: - leaq 384(%rsp),%rdi - call mont_mul_a3b - leaq 448(%rsp),%rsi - movq 40(%rsp),%rbp - addq $2,%rbp - movq %rbp,40(%rsp) - movq %rsi,%rcx - movq $8,%rax -loop_1: - movq (%rcx),%rbx - movw %bx,(%rbp) - shrq $16,%rbx - movw %bx,64(%rbp) - shrq $16,%rbx - movw %bx,128(%rbp) - shrq $16,%rbx - movw %bx,192(%rbp) - leaq 8(%rcx),%rcx - leaq 256(%rbp),%rbp - decq %rax - jnz loop_1 - movq 32(%rsp),%rax - subq $1,%rax - movq %rax,32(%rsp) - jne init_loop - - - - movdqa %xmm0,64(%rsp) - movdqa %xmm1,80(%rsp) - movdqa %xmm2,96(%rsp) - movdqa %xmm3,112(%rsp) - - - - - - movl 126(%rsp),%eax - movq %rax,%rdx - shrq $11,%rax - andl $2047,%edx - movl %edx,126(%rsp) - leaq 640(%rsp,%rax,2),%rsi - movq 8(%rsp),%rdx - movq $4,%rbp -loop_2: - movzwq 192(%rsi),%rbx - movzwq 448(%rsi),%rax - shlq $16,%rbx - shlq $16,%rax - movw 128(%rsi),%bx - movw 384(%rsi),%ax - shlq $16,%rbx - shlq $16,%rax - movw 64(%rsi),%bx - movw 320(%rsi),%ax - shlq $16,%rbx - shlq $16,%rax - movw 0(%rsi),%bx - movw 256(%rsi),%ax - movq %rbx,0(%rdx) - movq %rax,8(%rdx) - leaq 512(%rsi),%rsi - leaq 16(%rdx),%rdx - subq $1,%rbp - jnz loop_2 - movq $505,48(%rsp) - - movq 8(%rsp),%rcx - movq %rcx,136(%rsp) - movq 0(%rcx),%r10 - movq 8(%rcx),%r11 - movq 16(%rcx),%r12 - movq 24(%rcx),%r13 - movq 32(%rcx),%r14 - movq 40(%rcx),%r15 - movq 48(%rcx),%r8 - movq 56(%rcx),%r9 - jmp sqr_2 - -main_loop_a3b: - call sqr_reduce - call sqr_reduce - call sqr_reduce -sqr_2: - call sqr_reduce - call sqr_reduce - - - - movq 48(%rsp),%rcx - movq %rcx,%rax - shrq $4,%rax - movl 64(%rsp,%rax,2),%edx - andq $15,%rcx - shrq %cl,%rdx - andq $31,%rdx - - leaq 640(%rsp,%rdx,2),%rsi - leaq 448(%rsp),%rdx - movq %rdx,%rdi - movq $4,%rbp -loop_3: - movzwq 192(%rsi),%rbx - movzwq 448(%rsi),%rax - shlq $16,%rbx - shlq $16,%rax - movw 128(%rsi),%bx - movw 384(%rsi),%ax - shlq $16,%rbx - shlq $16,%rax - movw 64(%rsi),%bx - movw 320(%rsi),%ax - shlq $16,%rbx - shlq $16,%rax - movw 0(%rsi),%bx - movw 256(%rsi),%ax - movq %rbx,0(%rdx) - movq %rax,8(%rdx) - leaq 512(%rsi),%rsi - leaq 16(%rdx),%rdx - subq $1,%rbp - jnz loop_3 - movq 8(%rsp),%rsi - call mont_mul_a3b - - - - movq 48(%rsp),%rcx - subq $5,%rcx - movq %rcx,48(%rsp) - jge main_loop_a3b - - - -end_main_loop_a3b: - - - movq 8(%rsp),%rdx - pxor %xmm4,%xmm4 - movdqu 0(%rdx),%xmm0 - movdqu 16(%rdx),%xmm1 - movdqu 32(%rdx),%xmm2 - movdqu 48(%rdx),%xmm3 - movdqa %xmm4,576(%rsp) - movdqa %xmm4,592(%rsp) - movdqa %xmm4,608(%rsp) - movdqa %xmm4,624(%rsp) - movdqa %xmm0,512(%rsp) - movdqa %xmm1,528(%rsp) - movdqa %xmm2,544(%rsp) - movdqa %xmm3,560(%rsp) - call mont_reduce - - - - movq 8(%rsp),%rax - movq 0(%rax),%r8 - movq 8(%rax),%r9 - movq 16(%rax),%r10 - movq 24(%rax),%r11 - movq 32(%rax),%r12 - movq 40(%rax),%r13 - movq 48(%rax),%r14 - movq 56(%rax),%r15 - - - movq 24(%rsp),%rbx - addq $512,%rbx - - subq 0(%rbx),%r8 - sbbq 8(%rbx),%r9 - sbbq 16(%rbx),%r10 - sbbq 24(%rbx),%r11 - sbbq 32(%rbx),%r12 - sbbq 40(%rbx),%r13 - sbbq 48(%rbx),%r14 - sbbq 56(%rbx),%r15 - - - movq 0(%rax),%rsi - movq 8(%rax),%rdi - movq 16(%rax),%rcx - movq 24(%rax),%rdx - cmovncq %r8,%rsi - cmovncq %r9,%rdi - cmovncq %r10,%rcx - cmovncq %r11,%rdx - movq %rsi,0(%rax) - movq %rdi,8(%rax) - movq %rcx,16(%rax) - movq %rdx,24(%rax) - - movq 32(%rax),%rsi - movq 40(%rax),%rdi - movq 48(%rax),%rcx - movq 56(%rax),%rdx - cmovncq %r12,%rsi - cmovncq %r13,%rdi - cmovncq %r14,%rcx - cmovncq %r15,%rdx - movq %rsi,32(%rax) - movq %rdi,40(%rax) - movq %rcx,48(%rax) - movq %rdx,56(%rax) - - movq 0(%rsp),%rsi - movq 0(%rsi),%r15 - movq 8(%rsi),%r14 - movq 16(%rsi),%r13 - movq 24(%rsi),%r12 - movq 32(%rsi),%rbx - movq 40(%rsi),%rbp - leaq 48(%rsi),%rsp -.Lepilogue: - .byte 0xf3,0xc3 -.size mod_exp_512, . - mod_exp_512 -#endif
diff --git a/third_party/boringssl/mac-x86_64/crypto/bn/modexp512-x86_64.S b/third_party/boringssl/mac-x86_64/crypto/bn/modexp512-x86_64.S deleted file mode 100644 index beb133e..0000000 --- a/third_party/boringssl/mac-x86_64/crypto/bn/modexp512-x86_64.S +++ /dev/null
@@ -1,1776 +0,0 @@ -#if defined(__x86_64__) -.text - - -.p2align 4 -MULADD_128x512: - movq 0(%rsi),%rax - mulq %rbp - addq %rax,%r8 - adcq $0,%rdx - movq %r8,0(%rcx) - movq %rdx,%rbx - - movq 8(%rsi),%rax - mulq %rbp - addq %rax,%r9 - adcq $0,%rdx - addq %rbx,%r9 - adcq $0,%rdx - movq %rdx,%rbx - - movq 16(%rsi),%rax - mulq %rbp - addq %rax,%r10 - adcq $0,%rdx - addq %rbx,%r10 - adcq $0,%rdx - movq %rdx,%rbx - - movq 24(%rsi),%rax - mulq %rbp - addq %rax,%r11 - adcq $0,%rdx - addq %rbx,%r11 - adcq $0,%rdx - movq %rdx,%rbx - - movq 32(%rsi),%rax - mulq %rbp - addq %rax,%r12 - adcq $0,%rdx - addq %rbx,%r12 - adcq $0,%rdx - movq %rdx,%rbx - - movq 40(%rsi),%rax - mulq %rbp - addq %rax,%r13 - adcq $0,%rdx - addq %rbx,%r13 - adcq $0,%rdx - movq %rdx,%rbx - - movq 48(%rsi),%rax - mulq %rbp - addq %rax,%r14 - adcq $0,%rdx - addq %rbx,%r14 - adcq $0,%rdx - movq %rdx,%rbx - - movq 56(%rsi),%rax - mulq %rbp - addq %rax,%r15 - adcq $0,%rdx - addq %rbx,%r15 - adcq $0,%rdx - movq %rdx,%r8 - movq 8(%rdi),%rbp - movq 0(%rsi),%rax - mulq %rbp - addq %rax,%r9 - adcq $0,%rdx - movq %r9,8(%rcx) - movq %rdx,%rbx - - movq 8(%rsi),%rax - mulq %rbp - addq %rax,%r10 - adcq $0,%rdx - addq %rbx,%r10 - adcq $0,%rdx - movq %rdx,%rbx - - movq 16(%rsi),%rax - mulq %rbp - addq %rax,%r11 - adcq $0,%rdx - addq %rbx,%r11 - adcq $0,%rdx - movq %rdx,%rbx - - movq 24(%rsi),%rax - mulq %rbp - addq %rax,%r12 - adcq $0,%rdx - addq %rbx,%r12 - adcq $0,%rdx - movq %rdx,%rbx - - movq 32(%rsi),%rax - mulq %rbp - addq %rax,%r13 - adcq $0,%rdx - addq %rbx,%r13 - adcq $0,%rdx - movq %rdx,%rbx - - movq 40(%rsi),%rax - mulq %rbp - addq %rax,%r14 - adcq $0,%rdx - addq %rbx,%r14 - adcq $0,%rdx - movq %rdx,%rbx - - movq 48(%rsi),%rax - mulq %rbp - addq %rax,%r15 - adcq $0,%rdx - addq %rbx,%r15 - adcq $0,%rdx - movq %rdx,%rbx - - movq 56(%rsi),%rax - mulq %rbp - addq %rax,%r8 - adcq $0,%rdx - addq %rbx,%r8 - adcq $0,%rdx - movq %rdx,%r9 - .byte 0xf3,0xc3 - - -.p2align 4 -mont_reduce: - leaq 192(%rsp),%rdi - movq 32(%rsp),%rsi - addq $576,%rsi - leaq 520(%rsp),%rcx - - movq 96(%rcx),%rbp - movq 0(%rsi),%rax - mulq %rbp - movq (%rcx),%r8 - addq %rax,%r8 - adcq $0,%rdx - movq %r8,0(%rdi) - movq %rdx,%rbx - - movq 8(%rsi),%rax - mulq %rbp - movq 8(%rcx),%r9 - addq %rax,%r9 - adcq $0,%rdx - addq %rbx,%r9 - adcq $0,%rdx - movq %rdx,%rbx - - movq 16(%rsi),%rax - mulq %rbp - movq 16(%rcx),%r10 - addq %rax,%r10 - adcq $0,%rdx - addq %rbx,%r10 - adcq $0,%rdx - movq %rdx,%rbx - - movq 24(%rsi),%rax - mulq %rbp - movq 24(%rcx),%r11 - addq %rax,%r11 - adcq $0,%rdx - addq %rbx,%r11 - adcq $0,%rdx - movq %rdx,%rbx - - movq 32(%rsi),%rax - mulq %rbp - movq 32(%rcx),%r12 - addq %rax,%r12 - adcq $0,%rdx - addq %rbx,%r12 - adcq $0,%rdx - movq %rdx,%rbx - - movq 40(%rsi),%rax - mulq %rbp - movq 40(%rcx),%r13 - addq %rax,%r13 - adcq $0,%rdx - addq %rbx,%r13 - adcq $0,%rdx - movq %rdx,%rbx - - movq 48(%rsi),%rax - mulq %rbp - movq 48(%rcx),%r14 - addq %rax,%r14 - adcq $0,%rdx - addq %rbx,%r14 - adcq $0,%rdx - movq %rdx,%rbx - - movq 56(%rsi),%rax - mulq %rbp - movq 56(%rcx),%r15 - addq %rax,%r15 - adcq $0,%rdx - addq %rbx,%r15 - adcq $0,%rdx - movq %rdx,%r8 - movq 104(%rcx),%rbp - movq 0(%rsi),%rax - mulq %rbp - addq %rax,%r9 - adcq $0,%rdx - movq %r9,8(%rdi) - movq %rdx,%rbx - - movq 8(%rsi),%rax - mulq %rbp - addq %rax,%r10 - adcq $0,%rdx - addq %rbx,%r10 - adcq $0,%rdx - movq %rdx,%rbx - - movq 16(%rsi),%rax - mulq %rbp - addq %rax,%r11 - adcq $0,%rdx - addq %rbx,%r11 - adcq $0,%rdx - movq %rdx,%rbx - - movq 24(%rsi),%rax - mulq %rbp - addq %rax,%r12 - adcq $0,%rdx - addq %rbx,%r12 - adcq $0,%rdx - movq %rdx,%rbx - - movq 32(%rsi),%rax - mulq %rbp - addq %rax,%r13 - adcq $0,%rdx - addq %rbx,%r13 - adcq $0,%rdx - movq %rdx,%rbx - - movq 40(%rsi),%rax - mulq %rbp - addq %rax,%r14 - adcq $0,%rdx - addq %rbx,%r14 - adcq $0,%rdx - movq %rdx,%rbx - - movq 48(%rsi),%rax - mulq %rbp - addq %rax,%r15 - adcq $0,%rdx - addq %rbx,%r15 - adcq $0,%rdx - movq %rdx,%rbx - - movq 56(%rsi),%rax - mulq %rbp - addq %rax,%r8 - adcq $0,%rdx - addq %rbx,%r8 - adcq $0,%rdx - movq %rdx,%r9 - movq 112(%rcx),%rbp - movq 0(%rsi),%rax - mulq %rbp - addq %rax,%r10 - adcq $0,%rdx - movq %r10,16(%rdi) - movq %rdx,%rbx - - movq 8(%rsi),%rax - mulq %rbp - addq %rax,%r11 - adcq $0,%rdx - addq %rbx,%r11 - adcq $0,%rdx - movq %rdx,%rbx - - movq 16(%rsi),%rax - mulq %rbp - addq %rax,%r12 - adcq $0,%rdx - addq %rbx,%r12 - adcq $0,%rdx - movq %rdx,%rbx - - movq 24(%rsi),%rax - mulq %rbp - addq %rax,%r13 - adcq $0,%rdx - addq %rbx,%r13 - adcq $0,%rdx - movq %rdx,%rbx - - movq 32(%rsi),%rax - mulq %rbp - addq %rax,%r14 - adcq $0,%rdx - addq %rbx,%r14 - adcq $0,%rdx - movq %rdx,%rbx - - movq 40(%rsi),%rax - mulq %rbp - addq %rax,%r15 - adcq $0,%rdx - addq %rbx,%r15 - adcq $0,%rdx - movq %rdx,%rbx - - movq 48(%rsi),%rax - mulq %rbp - addq %rax,%r8 - adcq $0,%rdx - addq %rbx,%r8 - adcq $0,%rdx - movq %rdx,%rbx - - movq 56(%rsi),%rax - mulq %rbp - addq %rax,%r9 - adcq $0,%rdx - addq %rbx,%r9 - adcq $0,%rdx - movq %rdx,%r10 - movq 120(%rcx),%rbp - movq 0(%rsi),%rax - mulq %rbp - addq %rax,%r11 - adcq $0,%rdx - movq %r11,24(%rdi) - movq %rdx,%rbx - - movq 8(%rsi),%rax - mulq %rbp - addq %rax,%r12 - adcq $0,%rdx - addq %rbx,%r12 - adcq $0,%rdx - movq %rdx,%rbx - - movq 16(%rsi),%rax - mulq %rbp - addq %rax,%r13 - adcq $0,%rdx - addq %rbx,%r13 - adcq $0,%rdx - movq %rdx,%rbx - - movq 24(%rsi),%rax - mulq %rbp - addq %rax,%r14 - adcq $0,%rdx - addq %rbx,%r14 - adcq $0,%rdx - movq %rdx,%rbx - - movq 32(%rsi),%rax - mulq %rbp - addq %rax,%r15 - adcq $0,%rdx - addq %rbx,%r15 - adcq $0,%rdx - movq %rdx,%rbx - - movq 40(%rsi),%rax - mulq %rbp - addq %rax,%r8 - adcq $0,%rdx - addq %rbx,%r8 - adcq $0,%rdx - movq %rdx,%rbx - - movq 48(%rsi),%rax - mulq %rbp - addq %rax,%r9 - adcq $0,%rdx - addq %rbx,%r9 - adcq $0,%rdx - movq %rdx,%rbx - - movq 56(%rsi),%rax - mulq %rbp - addq %rax,%r10 - adcq $0,%rdx - addq %rbx,%r10 - adcq $0,%rdx - movq %rdx,%r11 - xorq %rax,%rax - - addq 64(%rcx),%r8 - adcq 72(%rcx),%r9 - adcq 80(%rcx),%r10 - adcq 88(%rcx),%r11 - adcq $0,%rax - - - - - movq %r8,64(%rdi) - movq %r9,72(%rdi) - movq %r10,%rbp - movq %r11,88(%rdi) - - movq %rax,384(%rsp) - - movq 0(%rdi),%r8 - movq 8(%rdi),%r9 - movq 16(%rdi),%r10 - movq 24(%rdi),%r11 - - - - - - - - - addq $80,%rdi - - addq $64,%rsi - leaq 296(%rsp),%rcx - - call MULADD_128x512 - - movq 384(%rsp),%rax - - - addq -16(%rdi),%r8 - adcq -8(%rdi),%r9 - movq %r8,64(%rcx) - movq %r9,72(%rcx) - - adcq %rax,%rax - movq %rax,384(%rsp) - - leaq 192(%rsp),%rdi - addq $64,%rsi - - - - - - movq (%rsi),%r8 - movq 8(%rsi),%rbx - - movq (%rcx),%rax - mulq %r8 - movq %rax,%rbp - movq %rdx,%r9 - - movq 8(%rcx),%rax - mulq %r8 - addq %rax,%r9 - - movq (%rcx),%rax - mulq %rbx - addq %rax,%r9 - - movq %r9,8(%rdi) - - - subq $192,%rsi - - movq (%rcx),%r8 - movq 8(%rcx),%r9 - - call MULADD_128x512 - - - - - movq 0(%rsi),%rax - movq 8(%rsi),%rbx - movq 16(%rsi),%rdi - movq 24(%rsi),%rdx - - - movq 384(%rsp),%rbp - - addq 64(%rcx),%r8 - adcq 72(%rcx),%r9 - - - adcq %rbp,%rbp - - - - shlq $3,%rbp - movq 32(%rsp),%rcx - addq %rcx,%rbp - - - xorq %rsi,%rsi - - addq 0(%rbp),%r10 - adcq 64(%rbp),%r11 - adcq 128(%rbp),%r12 - adcq 192(%rbp),%r13 - adcq 256(%rbp),%r14 - adcq 320(%rbp),%r15 - adcq 384(%rbp),%r8 - adcq 448(%rbp),%r9 - - - - sbbq $0,%rsi - - - andq %rsi,%rax - andq %rsi,%rbx - andq %rsi,%rdi - andq %rsi,%rdx - - movq $1,%rbp - subq %rax,%r10 - sbbq %rbx,%r11 - sbbq %rdi,%r12 - sbbq %rdx,%r13 - - - - - sbbq $0,%rbp - - - - addq $512,%rcx - movq 32(%rcx),%rax - movq 40(%rcx),%rbx - movq 48(%rcx),%rdi - movq 56(%rcx),%rdx - - - - andq %rsi,%rax - andq %rsi,%rbx - andq %rsi,%rdi - andq %rsi,%rdx - - - - subq $1,%rbp - - sbbq %rax,%r14 - sbbq %rbx,%r15 - sbbq %rdi,%r8 - sbbq %rdx,%r9 - - - - movq 144(%rsp),%rsi - movq %r10,0(%rsi) - movq %r11,8(%rsi) - movq %r12,16(%rsi) - movq %r13,24(%rsi) - movq %r14,32(%rsi) - movq %r15,40(%rsi) - movq %r8,48(%rsi) - movq %r9,56(%rsi) - - .byte 0xf3,0xc3 - - -.p2align 4 -mont_mul_a3b: - - - - - movq 0(%rdi),%rbp - - movq %r10,%rax - mulq %rbp - movq %rax,520(%rsp) - movq %rdx,%r10 - movq %r11,%rax - mulq %rbp - addq %rax,%r10 - adcq $0,%rdx - movq %rdx,%r11 - movq %r12,%rax - mulq %rbp - addq %rax,%r11 - adcq $0,%rdx - movq %rdx,%r12 - movq %r13,%rax - mulq %rbp - addq %rax,%r12 - adcq $0,%rdx - movq %rdx,%r13 - movq %r14,%rax - mulq %rbp - addq %rax,%r13 - adcq $0,%rdx - movq %rdx,%r14 - movq %r15,%rax - mulq %rbp - addq %rax,%r14 - adcq $0,%rdx - movq %rdx,%r15 - movq %r8,%rax - mulq %rbp - addq %rax,%r15 - adcq $0,%rdx - movq %rdx,%r8 - movq %r9,%rax - mulq %rbp - addq %rax,%r8 - adcq $0,%rdx - movq %rdx,%r9 - movq 8(%rdi),%rbp - movq 0(%rsi),%rax - mulq %rbp - addq %rax,%r10 - adcq $0,%rdx - movq %r10,528(%rsp) - movq %rdx,%rbx - - movq 8(%rsi),%rax - mulq %rbp - addq %rax,%r11 - adcq $0,%rdx - addq %rbx,%r11 - adcq $0,%rdx - movq %rdx,%rbx - - movq 16(%rsi),%rax - mulq %rbp - addq %rax,%r12 - adcq $0,%rdx - addq %rbx,%r12 - adcq $0,%rdx - movq %rdx,%rbx - - movq 24(%rsi),%rax - mulq %rbp - addq %rax,%r13 - adcq $0,%rdx - addq %rbx,%r13 - adcq $0,%rdx - movq %rdx,%rbx - - movq 32(%rsi),%rax - mulq %rbp - addq %rax,%r14 - adcq $0,%rdx - addq %rbx,%r14 - adcq $0,%rdx - movq %rdx,%rbx - - movq 40(%rsi),%rax - mulq %rbp - addq %rax,%r15 - adcq $0,%rdx - addq %rbx,%r15 - adcq $0,%rdx - movq %rdx,%rbx - - movq 48(%rsi),%rax - mulq %rbp - addq %rax,%r8 - adcq $0,%rdx - addq %rbx,%r8 - adcq $0,%rdx - movq %rdx,%rbx - - movq 56(%rsi),%rax - mulq %rbp - addq %rax,%r9 - adcq $0,%rdx - addq %rbx,%r9 - adcq $0,%rdx - movq %rdx,%r10 - movq 16(%rdi),%rbp - movq 0(%rsi),%rax - mulq %rbp - addq %rax,%r11 - adcq $0,%rdx - movq %r11,536(%rsp) - movq %rdx,%rbx - - movq 8(%rsi),%rax - mulq %rbp - addq %rax,%r12 - adcq $0,%rdx - addq %rbx,%r12 - adcq $0,%rdx - movq %rdx,%rbx - - movq 16(%rsi),%rax - mulq %rbp - addq %rax,%r13 - adcq $0,%rdx - addq %rbx,%r13 - adcq $0,%rdx - movq %rdx,%rbx - - movq 24(%rsi),%rax - mulq %rbp - addq %rax,%r14 - adcq $0,%rdx - addq %rbx,%r14 - adcq $0,%rdx - movq %rdx,%rbx - - movq 32(%rsi),%rax - mulq %rbp - addq %rax,%r15 - adcq $0,%rdx - addq %rbx,%r15 - adcq $0,%rdx - movq %rdx,%rbx - - movq 40(%rsi),%rax - mulq %rbp - addq %rax,%r8 - adcq $0,%rdx - addq %rbx,%r8 - adcq $0,%rdx - movq %rdx,%rbx - - movq 48(%rsi),%rax - mulq %rbp - addq %rax,%r9 - adcq $0,%rdx - addq %rbx,%r9 - adcq $0,%rdx - movq %rdx,%rbx - - movq 56(%rsi),%rax - mulq %rbp - addq %rax,%r10 - adcq $0,%rdx - addq %rbx,%r10 - adcq $0,%rdx - movq %rdx,%r11 - movq 24(%rdi),%rbp - movq 0(%rsi),%rax - mulq %rbp - addq %rax,%r12 - adcq $0,%rdx - movq %r12,544(%rsp) - movq %rdx,%rbx - - movq 8(%rsi),%rax - mulq %rbp - addq %rax,%r13 - adcq $0,%rdx - addq %rbx,%r13 - adcq $0,%rdx - movq %rdx,%rbx - - movq 16(%rsi),%rax - mulq %rbp - addq %rax,%r14 - adcq $0,%rdx - addq %rbx,%r14 - adcq $0,%rdx - movq %rdx,%rbx - - movq 24(%rsi),%rax - mulq %rbp - addq %rax,%r15 - adcq $0,%rdx - addq %rbx,%r15 - adcq $0,%rdx - movq %rdx,%rbx - - movq 32(%rsi),%rax - mulq %rbp - addq %rax,%r8 - adcq $0,%rdx - addq %rbx,%r8 - adcq $0,%rdx - movq %rdx,%rbx - - movq 40(%rsi),%rax - mulq %rbp - addq %rax,%r9 - adcq $0,%rdx - addq %rbx,%r9 - adcq $0,%rdx - movq %rdx,%rbx - - movq 48(%rsi),%rax - mulq %rbp - addq %rax,%r10 - adcq $0,%rdx - addq %rbx,%r10 - adcq $0,%rdx - movq %rdx,%rbx - - movq 56(%rsi),%rax - mulq %rbp - addq %rax,%r11 - adcq $0,%rdx - addq %rbx,%r11 - adcq $0,%rdx - movq %rdx,%r12 - movq 32(%rdi),%rbp - movq 0(%rsi),%rax - mulq %rbp - addq %rax,%r13 - adcq $0,%rdx - movq %r13,552(%rsp) - movq %rdx,%rbx - - movq 8(%rsi),%rax - mulq %rbp - addq %rax,%r14 - adcq $0,%rdx - addq %rbx,%r14 - adcq $0,%rdx - movq %rdx,%rbx - - movq 16(%rsi),%rax - mulq %rbp - addq %rax,%r15 - adcq $0,%rdx - addq %rbx,%r15 - adcq $0,%rdx - movq %rdx,%rbx - - movq 24(%rsi),%rax - mulq %rbp - addq %rax,%r8 - adcq $0,%rdx - addq %rbx,%r8 - adcq $0,%rdx - movq %rdx,%rbx - - movq 32(%rsi),%rax - mulq %rbp - addq %rax,%r9 - adcq $0,%rdx - addq %rbx,%r9 - adcq $0,%rdx - movq %rdx,%rbx - - movq 40(%rsi),%rax - mulq %rbp - addq %rax,%r10 - adcq $0,%rdx - addq %rbx,%r10 - adcq $0,%rdx - movq %rdx,%rbx - - movq 48(%rsi),%rax - mulq %rbp - addq %rax,%r11 - adcq $0,%rdx - addq %rbx,%r11 - adcq $0,%rdx - movq %rdx,%rbx - - movq 56(%rsi),%rax - mulq %rbp - addq %rax,%r12 - adcq $0,%rdx - addq %rbx,%r12 - adcq $0,%rdx - movq %rdx,%r13 - movq 40(%rdi),%rbp - movq 0(%rsi),%rax - mulq %rbp - addq %rax,%r14 - adcq $0,%rdx - movq %r14,560(%rsp) - movq %rdx,%rbx - - movq 8(%rsi),%rax - mulq %rbp - addq %rax,%r15 - adcq $0,%rdx - addq %rbx,%r15 - adcq $0,%rdx - movq %rdx,%rbx - - movq 16(%rsi),%rax - mulq %rbp - addq %rax,%r8 - adcq $0,%rdx - addq %rbx,%r8 - adcq $0,%rdx - movq %rdx,%rbx - - movq 24(%rsi),%rax - mulq %rbp - addq %rax,%r9 - adcq $0,%rdx - addq %rbx,%r9 - adcq $0,%rdx - movq %rdx,%rbx - - movq 32(%rsi),%rax - mulq %rbp - addq %rax,%r10 - adcq $0,%rdx - addq %rbx,%r10 - adcq $0,%rdx - movq %rdx,%rbx - - movq 40(%rsi),%rax - mulq %rbp - addq %rax,%r11 - adcq $0,%rdx - addq %rbx,%r11 - adcq $0,%rdx - movq %rdx,%rbx - - movq 48(%rsi),%rax - mulq %rbp - addq %rax,%r12 - adcq $0,%rdx - addq %rbx,%r12 - adcq $0,%rdx - movq %rdx,%rbx - - movq 56(%rsi),%rax - mulq %rbp - addq %rax,%r13 - adcq $0,%rdx - addq %rbx,%r13 - adcq $0,%rdx - movq %rdx,%r14 - movq 48(%rdi),%rbp - movq 0(%rsi),%rax - mulq %rbp - addq %rax,%r15 - adcq $0,%rdx - movq %r15,568(%rsp) - movq %rdx,%rbx - - movq 8(%rsi),%rax - mulq %rbp - addq %rax,%r8 - adcq $0,%rdx - addq %rbx,%r8 - adcq $0,%rdx - movq %rdx,%rbx - - movq 16(%rsi),%rax - mulq %rbp - addq %rax,%r9 - adcq $0,%rdx - addq %rbx,%r9 - adcq $0,%rdx - movq %rdx,%rbx - - movq 24(%rsi),%rax - mulq %rbp - addq %rax,%r10 - adcq $0,%rdx - addq %rbx,%r10 - adcq $0,%rdx - movq %rdx,%rbx - - movq 32(%rsi),%rax - mulq %rbp - addq %rax,%r11 - adcq $0,%rdx - addq %rbx,%r11 - adcq $0,%rdx - movq %rdx,%rbx - - movq 40(%rsi),%rax - mulq %rbp - addq %rax,%r12 - adcq $0,%rdx - addq %rbx,%r12 - adcq $0,%rdx - movq %rdx,%rbx - - movq 48(%rsi),%rax - mulq %rbp - addq %rax,%r13 - adcq $0,%rdx - addq %rbx,%r13 - adcq $0,%rdx - movq %rdx,%rbx - - movq 56(%rsi),%rax - mulq %rbp - addq %rax,%r14 - adcq $0,%rdx - addq %rbx,%r14 - adcq $0,%rdx - movq %rdx,%r15 - movq 56(%rdi),%rbp - movq 0(%rsi),%rax - mulq %rbp - addq %rax,%r8 - adcq $0,%rdx - movq %r8,576(%rsp) - movq %rdx,%rbx - - movq 8(%rsi),%rax - mulq %rbp - addq %rax,%r9 - adcq $0,%rdx - addq %rbx,%r9 - adcq $0,%rdx - movq %rdx,%rbx - - movq 16(%rsi),%rax - mulq %rbp - addq %rax,%r10 - adcq $0,%rdx - addq %rbx,%r10 - adcq $0,%rdx - movq %rdx,%rbx - - movq 24(%rsi),%rax - mulq %rbp - addq %rax,%r11 - adcq $0,%rdx - addq %rbx,%r11 - adcq $0,%rdx - movq %rdx,%rbx - - movq 32(%rsi),%rax - mulq %rbp - addq %rax,%r12 - adcq $0,%rdx - addq %rbx,%r12 - adcq $0,%rdx - movq %rdx,%rbx - - movq 40(%rsi),%rax - mulq %rbp - addq %rax,%r13 - adcq $0,%rdx - addq %rbx,%r13 - adcq $0,%rdx - movq %rdx,%rbx - - movq 48(%rsi),%rax - mulq %rbp - addq %rax,%r14 - adcq $0,%rdx - addq %rbx,%r14 - adcq $0,%rdx - movq %rdx,%rbx - - movq 56(%rsi),%rax - mulq %rbp - addq %rax,%r15 - adcq $0,%rdx - addq %rbx,%r15 - adcq $0,%rdx - movq %rdx,%r8 - movq %r9,584(%rsp) - movq %r10,592(%rsp) - movq %r11,600(%rsp) - movq %r12,608(%rsp) - movq %r13,616(%rsp) - movq %r14,624(%rsp) - movq %r15,632(%rsp) - movq %r8,640(%rsp) - - - - - - jmp mont_reduce - - - - -.p2align 4 -sqr_reduce: - movq 16(%rsp),%rcx - - - - movq %r10,%rbx - - movq %r11,%rax - mulq %rbx - movq %rax,528(%rsp) - movq %rdx,%r10 - movq %r12,%rax - mulq %rbx - addq %rax,%r10 - adcq $0,%rdx - movq %rdx,%r11 - movq %r13,%rax - mulq %rbx - addq %rax,%r11 - adcq $0,%rdx - movq %rdx,%r12 - movq %r14,%rax - mulq %rbx - addq %rax,%r12 - adcq $0,%rdx - movq %rdx,%r13 - movq %r15,%rax - mulq %rbx - addq %rax,%r13 - adcq $0,%rdx - movq %rdx,%r14 - movq %r8,%rax - mulq %rbx - addq %rax,%r14 - adcq $0,%rdx - movq %rdx,%r15 - movq %r9,%rax - mulq %rbx - addq %rax,%r15 - adcq $0,%rdx - movq %rdx,%rsi - - movq %r10,536(%rsp) - - - - - - movq 8(%rcx),%rbx - - movq 16(%rcx),%rax - mulq %rbx - addq %rax,%r11 - adcq $0,%rdx - movq %r11,544(%rsp) - - movq %rdx,%r10 - movq 24(%rcx),%rax - mulq %rbx - addq %rax,%r12 - adcq $0,%rdx - addq %r10,%r12 - adcq $0,%rdx - movq %r12,552(%rsp) - - movq %rdx,%r10 - movq 32(%rcx),%rax - mulq %rbx - addq %rax,%r13 - adcq $0,%rdx - addq %r10,%r13 - adcq $0,%rdx - - movq %rdx,%r10 - movq 40(%rcx),%rax - mulq %rbx - addq %rax,%r14 - adcq $0,%rdx - addq %r10,%r14 - adcq $0,%rdx - - movq %rdx,%r10 - movq %r8,%rax - mulq %rbx - addq %rax,%r15 - adcq $0,%rdx - addq %r10,%r15 - adcq $0,%rdx - - movq %rdx,%r10 - movq %r9,%rax - mulq %rbx - addq %rax,%rsi - adcq $0,%rdx - addq %r10,%rsi - adcq $0,%rdx - - movq %rdx,%r11 - - - - - movq 16(%rcx),%rbx - - movq 24(%rcx),%rax - mulq %rbx - addq %rax,%r13 - adcq $0,%rdx - movq %r13,560(%rsp) - - movq %rdx,%r10 - movq 32(%rcx),%rax - mulq %rbx - addq %rax,%r14 - adcq $0,%rdx - addq %r10,%r14 - adcq $0,%rdx - movq %r14,568(%rsp) - - movq %rdx,%r10 - movq 40(%rcx),%rax - mulq %rbx - addq %rax,%r15 - adcq $0,%rdx - addq %r10,%r15 - adcq $0,%rdx - - movq %rdx,%r10 - movq %r8,%rax - mulq %rbx - addq %rax,%rsi - adcq $0,%rdx - addq %r10,%rsi - adcq $0,%rdx - - movq %rdx,%r10 - movq %r9,%rax - mulq %rbx - addq %rax,%r11 - adcq $0,%rdx - addq %r10,%r11 - adcq $0,%rdx - - movq %rdx,%r12 - - - - - - movq 24(%rcx),%rbx - - movq 32(%rcx),%rax - mulq %rbx - addq %rax,%r15 - adcq $0,%rdx - movq %r15,576(%rsp) - - movq %rdx,%r10 - movq 40(%rcx),%rax - mulq %rbx - addq %rax,%rsi - adcq $0,%rdx - addq %r10,%rsi - adcq $0,%rdx - movq %rsi,584(%rsp) - - movq %rdx,%r10 - movq %r8,%rax - mulq %rbx - addq %rax,%r11 - adcq $0,%rdx - addq %r10,%r11 - adcq $0,%rdx - - movq %rdx,%r10 - movq %r9,%rax - mulq %rbx - addq %rax,%r12 - adcq $0,%rdx - addq %r10,%r12 - adcq $0,%rdx - - movq %rdx,%r15 - - - - - movq 32(%rcx),%rbx - - movq 40(%rcx),%rax - mulq %rbx - addq %rax,%r11 - adcq $0,%rdx - movq %r11,592(%rsp) - - movq %rdx,%r10 - movq %r8,%rax - mulq %rbx - addq %rax,%r12 - adcq $0,%rdx - addq %r10,%r12 - adcq $0,%rdx - movq %r12,600(%rsp) - - movq %rdx,%r10 - movq %r9,%rax - mulq %rbx - addq %rax,%r15 - adcq $0,%rdx - addq %r10,%r15 - adcq $0,%rdx - - movq %rdx,%r11 - - - - - movq 40(%rcx),%rbx - - movq %r8,%rax - mulq %rbx - addq %rax,%r15 - adcq $0,%rdx - movq %r15,608(%rsp) - - movq %rdx,%r10 - movq %r9,%rax - mulq %rbx - addq %rax,%r11 - adcq $0,%rdx - addq %r10,%r11 - adcq $0,%rdx - movq %r11,616(%rsp) - - movq %rdx,%r12 - - - - - movq %r8,%rbx - - movq %r9,%rax - mulq %rbx - addq %rax,%r12 - adcq $0,%rdx - movq %r12,624(%rsp) - - movq %rdx,632(%rsp) - - - movq 528(%rsp),%r10 - movq 536(%rsp),%r11 - movq 544(%rsp),%r12 - movq 552(%rsp),%r13 - movq 560(%rsp),%r14 - movq 568(%rsp),%r15 - - movq 24(%rcx),%rax - mulq %rax - movq %rax,%rdi - movq %rdx,%r8 - - addq %r10,%r10 - adcq %r11,%r11 - adcq %r12,%r12 - adcq %r13,%r13 - adcq %r14,%r14 - adcq %r15,%r15 - adcq $0,%r8 - - movq 0(%rcx),%rax - mulq %rax - movq %rax,520(%rsp) - movq %rdx,%rbx - - movq 8(%rcx),%rax - mulq %rax - - addq %rbx,%r10 - adcq %rax,%r11 - adcq $0,%rdx - - movq %rdx,%rbx - movq %r10,528(%rsp) - movq %r11,536(%rsp) - - movq 16(%rcx),%rax - mulq %rax - - addq %rbx,%r12 - adcq %rax,%r13 - adcq $0,%rdx - - movq %rdx,%rbx - - movq %r12,544(%rsp) - movq %r13,552(%rsp) - - xorq %rbp,%rbp - addq %rbx,%r14 - adcq %rdi,%r15 - adcq $0,%rbp - - movq %r14,560(%rsp) - movq %r15,568(%rsp) - - - - - movq 576(%rsp),%r10 - movq 584(%rsp),%r11 - movq 592(%rsp),%r12 - movq 600(%rsp),%r13 - movq 608(%rsp),%r14 - movq 616(%rsp),%r15 - movq 624(%rsp),%rdi - movq 632(%rsp),%rsi - - movq %r9,%rax - mulq %rax - movq %rax,%r9 - movq %rdx,%rbx - - addq %r10,%r10 - adcq %r11,%r11 - adcq %r12,%r12 - adcq %r13,%r13 - adcq %r14,%r14 - adcq %r15,%r15 - adcq %rdi,%rdi - adcq %rsi,%rsi - adcq $0,%rbx - - addq %rbp,%r10 - - movq 32(%rcx),%rax - mulq %rax - - addq %r8,%r10 - adcq %rax,%r11 - adcq $0,%rdx - - movq %rdx,%rbp - - movq %r10,576(%rsp) - movq %r11,584(%rsp) - - movq 40(%rcx),%rax - mulq %rax - - addq %rbp,%r12 - adcq %rax,%r13 - adcq $0,%rdx - - movq %rdx,%rbp - - movq %r12,592(%rsp) - movq %r13,600(%rsp) - - movq 48(%rcx),%rax - mulq %rax - - addq %rbp,%r14 - adcq %rax,%r15 - adcq $0,%rdx - - movq %r14,608(%rsp) - movq %r15,616(%rsp) - - addq %rdx,%rdi - adcq %r9,%rsi - adcq $0,%rbx - - movq %rdi,624(%rsp) - movq %rsi,632(%rsp) - movq %rbx,640(%rsp) - - jmp mont_reduce - - - -.globl _mod_exp_512 -.private_extern _mod_exp_512 - -_mod_exp_512: - pushq %rbp - pushq %rbx - pushq %r12 - pushq %r13 - pushq %r14 - pushq %r15 - - - movq %rsp,%r8 - subq $2688,%rsp - andq $-64,%rsp - - - movq %r8,0(%rsp) - movq %rdi,8(%rsp) - movq %rsi,16(%rsp) - movq %rcx,24(%rsp) -L$body: - - - - pxor %xmm4,%xmm4 - movdqu 0(%rsi),%xmm0 - movdqu 16(%rsi),%xmm1 - movdqu 32(%rsi),%xmm2 - movdqu 48(%rsi),%xmm3 - movdqa %xmm4,512(%rsp) - movdqa %xmm4,528(%rsp) - movdqa %xmm4,608(%rsp) - movdqa %xmm4,624(%rsp) - movdqa %xmm0,544(%rsp) - movdqa %xmm1,560(%rsp) - movdqa %xmm2,576(%rsp) - movdqa %xmm3,592(%rsp) - - - movdqu 0(%rdx),%xmm0 - movdqu 16(%rdx),%xmm1 - movdqu 32(%rdx),%xmm2 - movdqu 48(%rdx),%xmm3 - - leaq 384(%rsp),%rbx - movq %rbx,136(%rsp) - call mont_reduce - - - leaq 448(%rsp),%rcx - xorq %rax,%rax - movq %rax,0(%rcx) - movq %rax,8(%rcx) - movq %rax,24(%rcx) - movq %rax,32(%rcx) - movq %rax,40(%rcx) - movq %rax,48(%rcx) - movq %rax,56(%rcx) - movq %rax,128(%rsp) - movq $1,16(%rcx) - - leaq 640(%rsp),%rbp - movq %rcx,%rsi - movq %rbp,%rdi - movq $8,%rax -loop_0: - movq (%rcx),%rbx - movw %bx,(%rdi) - shrq $16,%rbx - movw %bx,64(%rdi) - shrq $16,%rbx - movw %bx,128(%rdi) - shrq $16,%rbx - movw %bx,192(%rdi) - leaq 8(%rcx),%rcx - leaq 256(%rdi),%rdi - decq %rax - jnz loop_0 - movq $31,%rax - movq %rax,32(%rsp) - movq %rbp,40(%rsp) - - movq %rsi,136(%rsp) - movq 0(%rsi),%r10 - movq 8(%rsi),%r11 - movq 16(%rsi),%r12 - movq 24(%rsi),%r13 - movq 32(%rsi),%r14 - movq 40(%rsi),%r15 - movq 48(%rsi),%r8 - movq 56(%rsi),%r9 -init_loop: - leaq 384(%rsp),%rdi - call mont_mul_a3b - leaq 448(%rsp),%rsi - movq 40(%rsp),%rbp - addq $2,%rbp - movq %rbp,40(%rsp) - movq %rsi,%rcx - movq $8,%rax -loop_1: - movq (%rcx),%rbx - movw %bx,(%rbp) - shrq $16,%rbx - movw %bx,64(%rbp) - shrq $16,%rbx - movw %bx,128(%rbp) - shrq $16,%rbx - movw %bx,192(%rbp) - leaq 8(%rcx),%rcx - leaq 256(%rbp),%rbp - decq %rax - jnz loop_1 - movq 32(%rsp),%rax - subq $1,%rax - movq %rax,32(%rsp) - jne init_loop - - - - movdqa %xmm0,64(%rsp) - movdqa %xmm1,80(%rsp) - movdqa %xmm2,96(%rsp) - movdqa %xmm3,112(%rsp) - - - - - - movl 126(%rsp),%eax - movq %rax,%rdx - shrq $11,%rax - andl $2047,%edx - movl %edx,126(%rsp) - leaq 640(%rsp,%rax,2),%rsi - movq 8(%rsp),%rdx - movq $4,%rbp -loop_2: - movzwq 192(%rsi),%rbx - movzwq 448(%rsi),%rax - shlq $16,%rbx - shlq $16,%rax - movw 128(%rsi),%bx - movw 384(%rsi),%ax - shlq $16,%rbx - shlq $16,%rax - movw 64(%rsi),%bx - movw 320(%rsi),%ax - shlq $16,%rbx - shlq $16,%rax - movw 0(%rsi),%bx - movw 256(%rsi),%ax - movq %rbx,0(%rdx) - movq %rax,8(%rdx) - leaq 512(%rsi),%rsi - leaq 16(%rdx),%rdx - subq $1,%rbp - jnz loop_2 - movq $505,48(%rsp) - - movq 8(%rsp),%rcx - movq %rcx,136(%rsp) - movq 0(%rcx),%r10 - movq 8(%rcx),%r11 - movq 16(%rcx),%r12 - movq 24(%rcx),%r13 - movq 32(%rcx),%r14 - movq 40(%rcx),%r15 - movq 48(%rcx),%r8 - movq 56(%rcx),%r9 - jmp sqr_2 - -main_loop_a3b: - call sqr_reduce - call sqr_reduce - call sqr_reduce -sqr_2: - call sqr_reduce - call sqr_reduce - - - - movq 48(%rsp),%rcx - movq %rcx,%rax - shrq $4,%rax - movl 64(%rsp,%rax,2),%edx - andq $15,%rcx - shrq %cl,%rdx - andq $31,%rdx - - leaq 640(%rsp,%rdx,2),%rsi - leaq 448(%rsp),%rdx - movq %rdx,%rdi - movq $4,%rbp -loop_3: - movzwq 192(%rsi),%rbx - movzwq 448(%rsi),%rax - shlq $16,%rbx - shlq $16,%rax - movw 128(%rsi),%bx - movw 384(%rsi),%ax - shlq $16,%rbx - shlq $16,%rax - movw 64(%rsi),%bx - movw 320(%rsi),%ax - shlq $16,%rbx - shlq $16,%rax - movw 0(%rsi),%bx - movw 256(%rsi),%ax - movq %rbx,0(%rdx) - movq %rax,8(%rdx) - leaq 512(%rsi),%rsi - leaq 16(%rdx),%rdx - subq $1,%rbp - jnz loop_3 - movq 8(%rsp),%rsi - call mont_mul_a3b - - - - movq 48(%rsp),%rcx - subq $5,%rcx - movq %rcx,48(%rsp) - jge main_loop_a3b - - - -end_main_loop_a3b: - - - movq 8(%rsp),%rdx - pxor %xmm4,%xmm4 - movdqu 0(%rdx),%xmm0 - movdqu 16(%rdx),%xmm1 - movdqu 32(%rdx),%xmm2 - movdqu 48(%rdx),%xmm3 - movdqa %xmm4,576(%rsp) - movdqa %xmm4,592(%rsp) - movdqa %xmm4,608(%rsp) - movdqa %xmm4,624(%rsp) - movdqa %xmm0,512(%rsp) - movdqa %xmm1,528(%rsp) - movdqa %xmm2,544(%rsp) - movdqa %xmm3,560(%rsp) - call mont_reduce - - - - movq 8(%rsp),%rax - movq 0(%rax),%r8 - movq 8(%rax),%r9 - movq 16(%rax),%r10 - movq 24(%rax),%r11 - movq 32(%rax),%r12 - movq 40(%rax),%r13 - movq 48(%rax),%r14 - movq 56(%rax),%r15 - - - movq 24(%rsp),%rbx - addq $512,%rbx - - subq 0(%rbx),%r8 - sbbq 8(%rbx),%r9 - sbbq 16(%rbx),%r10 - sbbq 24(%rbx),%r11 - sbbq 32(%rbx),%r12 - sbbq 40(%rbx),%r13 - sbbq 48(%rbx),%r14 - sbbq 56(%rbx),%r15 - - - movq 0(%rax),%rsi - movq 8(%rax),%rdi - movq 16(%rax),%rcx - movq 24(%rax),%rdx - cmovncq %r8,%rsi - cmovncq %r9,%rdi - cmovncq %r10,%rcx - cmovncq %r11,%rdx - movq %rsi,0(%rax) - movq %rdi,8(%rax) - movq %rcx,16(%rax) - movq %rdx,24(%rax) - - movq 32(%rax),%rsi - movq 40(%rax),%rdi - movq 48(%rax),%rcx - movq 56(%rax),%rdx - cmovncq %r12,%rsi - cmovncq %r13,%rdi - cmovncq %r14,%rcx - cmovncq %r15,%rdx - movq %rsi,32(%rax) - movq %rdi,40(%rax) - movq %rcx,48(%rax) - movq %rdx,56(%rax) - - movq 0(%rsp),%rsi - movq 0(%rsi),%r15 - movq 8(%rsi),%r14 - movq 16(%rsi),%r13 - movq 24(%rsi),%r12 - movq 32(%rsi),%rbx - movq 40(%rsi),%rbp - leaq 48(%rsi),%rsp -L$epilogue: - .byte 0xf3,0xc3 - -#endif
diff --git a/third_party/boringssl/win-x86_64/crypto/bn/modexp512-x86_64.asm b/third_party/boringssl/win-x86_64/crypto/bn/modexp512-x86_64.asm deleted file mode 100644 index f3b306ef..0000000 --- a/third_party/boringssl/win-x86_64/crypto/bn/modexp512-x86_64.asm +++ /dev/null
@@ -1,1885 +0,0 @@ -default rel -%define XMMWORD -%define YMMWORD -%define ZMMWORD -section .text code align=64 - - - -ALIGN 16 -MULADD_128x512: - mov rax,QWORD[rsi] - mul rbp - add r8,rax - adc rdx,0 - mov QWORD[rcx],r8 - mov rbx,rdx - - mov rax,QWORD[8+rsi] - mul rbp - add r9,rax - adc rdx,0 - add r9,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[16+rsi] - mul rbp - add r10,rax - adc rdx,0 - add r10,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[24+rsi] - mul rbp - add r11,rax - adc rdx,0 - add r11,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[32+rsi] - mul rbp - add r12,rax - adc rdx,0 - add r12,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[40+rsi] - mul rbp - add r13,rax - adc rdx,0 - add r13,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[48+rsi] - mul rbp - add r14,rax - adc rdx,0 - add r14,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[56+rsi] - mul rbp - add r15,rax - adc rdx,0 - add r15,rbx - adc rdx,0 - mov r8,rdx - mov rbp,QWORD[8+rdi] - mov rax,QWORD[rsi] - mul rbp - add r9,rax - adc rdx,0 - mov QWORD[8+rcx],r9 - mov rbx,rdx - - mov rax,QWORD[8+rsi] - mul rbp - add r10,rax - adc rdx,0 - add r10,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[16+rsi] - mul rbp - add r11,rax - adc rdx,0 - add r11,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[24+rsi] - mul rbp - add r12,rax - adc rdx,0 - add r12,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[32+rsi] - mul rbp - add r13,rax - adc rdx,0 - add r13,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[40+rsi] - mul rbp - add r14,rax - adc rdx,0 - add r14,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[48+rsi] - mul rbp - add r15,rax - adc rdx,0 - add r15,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[56+rsi] - mul rbp - add r8,rax - adc rdx,0 - add r8,rbx - adc rdx,0 - mov r9,rdx - DB 0F3h,0C3h ;repret - - -ALIGN 16 -mont_reduce: - lea rdi,[192+rsp] - mov rsi,QWORD[32+rsp] - add rsi,576 - lea rcx,[520+rsp] - - mov rbp,QWORD[96+rcx] - mov rax,QWORD[rsi] - mul rbp - mov r8,QWORD[rcx] - add r8,rax - adc rdx,0 - mov QWORD[rdi],r8 - mov rbx,rdx - - mov rax,QWORD[8+rsi] - mul rbp - mov r9,QWORD[8+rcx] - add r9,rax - adc rdx,0 - add r9,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[16+rsi] - mul rbp - mov r10,QWORD[16+rcx] - add r10,rax - adc rdx,0 - add r10,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[24+rsi] - mul rbp - mov r11,QWORD[24+rcx] - add r11,rax - adc rdx,0 - add r11,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[32+rsi] - mul rbp - mov r12,QWORD[32+rcx] - add r12,rax - adc rdx,0 - add r12,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[40+rsi] - mul rbp - mov r13,QWORD[40+rcx] - add r13,rax - adc rdx,0 - add r13,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[48+rsi] - mul rbp - mov r14,QWORD[48+rcx] - add r14,rax - adc rdx,0 - add r14,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[56+rsi] - mul rbp - mov r15,QWORD[56+rcx] - add r15,rax - adc rdx,0 - add r15,rbx - adc rdx,0 - mov r8,rdx - mov rbp,QWORD[104+rcx] - mov rax,QWORD[rsi] - mul rbp - add r9,rax - adc rdx,0 - mov QWORD[8+rdi],r9 - mov rbx,rdx - - mov rax,QWORD[8+rsi] - mul rbp - add r10,rax - adc rdx,0 - add r10,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[16+rsi] - mul rbp - add r11,rax - adc rdx,0 - add r11,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[24+rsi] - mul rbp - add r12,rax - adc rdx,0 - add r12,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[32+rsi] - mul rbp - add r13,rax - adc rdx,0 - add r13,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[40+rsi] - mul rbp - add r14,rax - adc rdx,0 - add r14,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[48+rsi] - mul rbp - add r15,rax - adc rdx,0 - add r15,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[56+rsi] - mul rbp - add r8,rax - adc rdx,0 - add r8,rbx - adc rdx,0 - mov r9,rdx - mov rbp,QWORD[112+rcx] - mov rax,QWORD[rsi] - mul rbp - add r10,rax - adc rdx,0 - mov QWORD[16+rdi],r10 - mov rbx,rdx - - mov rax,QWORD[8+rsi] - mul rbp - add r11,rax - adc rdx,0 - add r11,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[16+rsi] - mul rbp - add r12,rax - adc rdx,0 - add r12,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[24+rsi] - mul rbp - add r13,rax - adc rdx,0 - add r13,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[32+rsi] - mul rbp - add r14,rax - adc rdx,0 - add r14,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[40+rsi] - mul rbp - add r15,rax - adc rdx,0 - add r15,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[48+rsi] - mul rbp - add r8,rax - adc rdx,0 - add r8,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[56+rsi] - mul rbp - add r9,rax - adc rdx,0 - add r9,rbx - adc rdx,0 - mov r10,rdx - mov rbp,QWORD[120+rcx] - mov rax,QWORD[rsi] - mul rbp - add r11,rax - adc rdx,0 - mov QWORD[24+rdi],r11 - mov rbx,rdx - - mov rax,QWORD[8+rsi] - mul rbp - add r12,rax - adc rdx,0 - add r12,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[16+rsi] - mul rbp - add r13,rax - adc rdx,0 - add r13,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[24+rsi] - mul rbp - add r14,rax - adc rdx,0 - add r14,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[32+rsi] - mul rbp - add r15,rax - adc rdx,0 - add r15,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[40+rsi] - mul rbp - add r8,rax - adc rdx,0 - add r8,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[48+rsi] - mul rbp - add r9,rax - adc rdx,0 - add r9,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[56+rsi] - mul rbp - add r10,rax - adc rdx,0 - add r10,rbx - adc rdx,0 - mov r11,rdx - xor rax,rax - - add r8,QWORD[64+rcx] - adc r9,QWORD[72+rcx] - adc r10,QWORD[80+rcx] - adc r11,QWORD[88+rcx] - adc rax,0 - - - - - mov QWORD[64+rdi],r8 - mov QWORD[72+rdi],r9 - mov rbp,r10 - mov QWORD[88+rdi],r11 - - mov QWORD[384+rsp],rax - - mov r8,QWORD[rdi] - mov r9,QWORD[8+rdi] - mov r10,QWORD[16+rdi] - mov r11,QWORD[24+rdi] - - - - - - - - - add rdi,8*10 - - add rsi,64 - lea rcx,[296+rsp] - - call MULADD_128x512 - - mov rax,QWORD[384+rsp] - - - add r8,QWORD[((-16))+rdi] - adc r9,QWORD[((-8))+rdi] - mov QWORD[64+rcx],r8 - mov QWORD[72+rcx],r9 - - adc rax,rax - mov QWORD[384+rsp],rax - - lea rdi,[192+rsp] - add rsi,64 - - - - - - mov r8,QWORD[rsi] - mov rbx,QWORD[8+rsi] - - mov rax,QWORD[rcx] - mul r8 - mov rbp,rax - mov r9,rdx - - mov rax,QWORD[8+rcx] - mul r8 - add r9,rax - - mov rax,QWORD[rcx] - mul rbx - add r9,rax - - mov QWORD[8+rdi],r9 - - - sub rsi,192 - - mov r8,QWORD[rcx] - mov r9,QWORD[8+rcx] - - call MULADD_128x512 - - - - - mov rax,QWORD[rsi] - mov rbx,QWORD[8+rsi] - mov rdi,QWORD[16+rsi] - mov rdx,QWORD[24+rsi] - - - mov rbp,QWORD[384+rsp] - - add r8,QWORD[64+rcx] - adc r9,QWORD[72+rcx] - - - adc rbp,rbp - - - - shl rbp,3 - mov rcx,QWORD[32+rsp] - add rbp,rcx - - - xor rsi,rsi - - add r10,QWORD[rbp] - adc r11,QWORD[64+rbp] - adc r12,QWORD[128+rbp] - adc r13,QWORD[192+rbp] - adc r14,QWORD[256+rbp] - adc r15,QWORD[320+rbp] - adc r8,QWORD[384+rbp] - adc r9,QWORD[448+rbp] - - - - sbb rsi,0 - - - and rax,rsi - and rbx,rsi - and rdi,rsi - and rdx,rsi - - mov rbp,1 - sub r10,rax - sbb r11,rbx - sbb r12,rdi - sbb r13,rdx - - - - - sbb rbp,0 - - - - add rcx,512 - mov rax,QWORD[32+rcx] - mov rbx,QWORD[40+rcx] - mov rdi,QWORD[48+rcx] - mov rdx,QWORD[56+rcx] - - - - and rax,rsi - and rbx,rsi - and rdi,rsi - and rdx,rsi - - - - sub rbp,1 - - sbb r14,rax - sbb r15,rbx - sbb r8,rdi - sbb r9,rdx - - - - mov rsi,QWORD[144+rsp] - mov QWORD[rsi],r10 - mov QWORD[8+rsi],r11 - mov QWORD[16+rsi],r12 - mov QWORD[24+rsi],r13 - mov QWORD[32+rsi],r14 - mov QWORD[40+rsi],r15 - mov QWORD[48+rsi],r8 - mov QWORD[56+rsi],r9 - - DB 0F3h,0C3h ;repret - - -ALIGN 16 -mont_mul_a3b: - - - - - mov rbp,QWORD[rdi] - - mov rax,r10 - mul rbp - mov QWORD[520+rsp],rax - mov r10,rdx - mov rax,r11 - mul rbp - add r10,rax - adc rdx,0 - mov r11,rdx - mov rax,r12 - mul rbp - add r11,rax - adc rdx,0 - mov r12,rdx - mov rax,r13 - mul rbp - add r12,rax - adc rdx,0 - mov r13,rdx - mov rax,r14 - mul rbp - add r13,rax - adc rdx,0 - mov r14,rdx - mov rax,r15 - mul rbp - add r14,rax - adc rdx,0 - mov r15,rdx - mov rax,r8 - mul rbp - add r15,rax - adc rdx,0 - mov r8,rdx - mov rax,r9 - mul rbp - add r8,rax - adc rdx,0 - mov r9,rdx - mov rbp,QWORD[8+rdi] - mov rax,QWORD[rsi] - mul rbp - add r10,rax - adc rdx,0 - mov QWORD[528+rsp],r10 - mov rbx,rdx - - mov rax,QWORD[8+rsi] - mul rbp - add r11,rax - adc rdx,0 - add r11,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[16+rsi] - mul rbp - add r12,rax - adc rdx,0 - add r12,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[24+rsi] - mul rbp - add r13,rax - adc rdx,0 - add r13,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[32+rsi] - mul rbp - add r14,rax - adc rdx,0 - add r14,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[40+rsi] - mul rbp - add r15,rax - adc rdx,0 - add r15,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[48+rsi] - mul rbp - add r8,rax - adc rdx,0 - add r8,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[56+rsi] - mul rbp - add r9,rax - adc rdx,0 - add r9,rbx - adc rdx,0 - mov r10,rdx - mov rbp,QWORD[16+rdi] - mov rax,QWORD[rsi] - mul rbp - add r11,rax - adc rdx,0 - mov QWORD[536+rsp],r11 - mov rbx,rdx - - mov rax,QWORD[8+rsi] - mul rbp - add r12,rax - adc rdx,0 - add r12,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[16+rsi] - mul rbp - add r13,rax - adc rdx,0 - add r13,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[24+rsi] - mul rbp - add r14,rax - adc rdx,0 - add r14,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[32+rsi] - mul rbp - add r15,rax - adc rdx,0 - add r15,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[40+rsi] - mul rbp - add r8,rax - adc rdx,0 - add r8,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[48+rsi] - mul rbp - add r9,rax - adc rdx,0 - add r9,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[56+rsi] - mul rbp - add r10,rax - adc rdx,0 - add r10,rbx - adc rdx,0 - mov r11,rdx - mov rbp,QWORD[24+rdi] - mov rax,QWORD[rsi] - mul rbp - add r12,rax - adc rdx,0 - mov QWORD[544+rsp],r12 - mov rbx,rdx - - mov rax,QWORD[8+rsi] - mul rbp - add r13,rax - adc rdx,0 - add r13,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[16+rsi] - mul rbp - add r14,rax - adc rdx,0 - add r14,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[24+rsi] - mul rbp - add r15,rax - adc rdx,0 - add r15,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[32+rsi] - mul rbp - add r8,rax - adc rdx,0 - add r8,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[40+rsi] - mul rbp - add r9,rax - adc rdx,0 - add r9,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[48+rsi] - mul rbp - add r10,rax - adc rdx,0 - add r10,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[56+rsi] - mul rbp - add r11,rax - adc rdx,0 - add r11,rbx - adc rdx,0 - mov r12,rdx - mov rbp,QWORD[32+rdi] - mov rax,QWORD[rsi] - mul rbp - add r13,rax - adc rdx,0 - mov QWORD[552+rsp],r13 - mov rbx,rdx - - mov rax,QWORD[8+rsi] - mul rbp - add r14,rax - adc rdx,0 - add r14,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[16+rsi] - mul rbp - add r15,rax - adc rdx,0 - add r15,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[24+rsi] - mul rbp - add r8,rax - adc rdx,0 - add r8,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[32+rsi] - mul rbp - add r9,rax - adc rdx,0 - add r9,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[40+rsi] - mul rbp - add r10,rax - adc rdx,0 - add r10,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[48+rsi] - mul rbp - add r11,rax - adc rdx,0 - add r11,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[56+rsi] - mul rbp - add r12,rax - adc rdx,0 - add r12,rbx - adc rdx,0 - mov r13,rdx - mov rbp,QWORD[40+rdi] - mov rax,QWORD[rsi] - mul rbp - add r14,rax - adc rdx,0 - mov QWORD[560+rsp],r14 - mov rbx,rdx - - mov rax,QWORD[8+rsi] - mul rbp - add r15,rax - adc rdx,0 - add r15,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[16+rsi] - mul rbp - add r8,rax - adc rdx,0 - add r8,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[24+rsi] - mul rbp - add r9,rax - adc rdx,0 - add r9,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[32+rsi] - mul rbp - add r10,rax - adc rdx,0 - add r10,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[40+rsi] - mul rbp - add r11,rax - adc rdx,0 - add r11,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[48+rsi] - mul rbp - add r12,rax - adc rdx,0 - add r12,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[56+rsi] - mul rbp - add r13,rax - adc rdx,0 - add r13,rbx - adc rdx,0 - mov r14,rdx - mov rbp,QWORD[48+rdi] - mov rax,QWORD[rsi] - mul rbp - add r15,rax - adc rdx,0 - mov QWORD[568+rsp],r15 - mov rbx,rdx - - mov rax,QWORD[8+rsi] - mul rbp - add r8,rax - adc rdx,0 - add r8,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[16+rsi] - mul rbp - add r9,rax - adc rdx,0 - add r9,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[24+rsi] - mul rbp - add r10,rax - adc rdx,0 - add r10,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[32+rsi] - mul rbp - add r11,rax - adc rdx,0 - add r11,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[40+rsi] - mul rbp - add r12,rax - adc rdx,0 - add r12,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[48+rsi] - mul rbp - add r13,rax - adc rdx,0 - add r13,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[56+rsi] - mul rbp - add r14,rax - adc rdx,0 - add r14,rbx - adc rdx,0 - mov r15,rdx - mov rbp,QWORD[56+rdi] - mov rax,QWORD[rsi] - mul rbp - add r8,rax - adc rdx,0 - mov QWORD[576+rsp],r8 - mov rbx,rdx - - mov rax,QWORD[8+rsi] - mul rbp - add r9,rax - adc rdx,0 - add r9,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[16+rsi] - mul rbp - add r10,rax - adc rdx,0 - add r10,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[24+rsi] - mul rbp - add r11,rax - adc rdx,0 - add r11,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[32+rsi] - mul rbp - add r12,rax - adc rdx,0 - add r12,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[40+rsi] - mul rbp - add r13,rax - adc rdx,0 - add r13,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[48+rsi] - mul rbp - add r14,rax - adc rdx,0 - add r14,rbx - adc rdx,0 - mov rbx,rdx - - mov rax,QWORD[56+rsi] - mul rbp - add r15,rax - adc rdx,0 - add r15,rbx - adc rdx,0 - mov r8,rdx - mov QWORD[584+rsp],r9 - mov QWORD[592+rsp],r10 - mov QWORD[600+rsp],r11 - mov QWORD[608+rsp],r12 - mov QWORD[616+rsp],r13 - mov QWORD[624+rsp],r14 - mov QWORD[632+rsp],r15 - mov QWORD[640+rsp],r8 - - - - - - jmp NEAR mont_reduce - - - - -ALIGN 16 -sqr_reduce: - mov rcx,QWORD[16+rsp] - - - - mov rbx,r10 - - mov rax,r11 - mul rbx - mov QWORD[528+rsp],rax - mov r10,rdx - mov rax,r12 - mul rbx - add r10,rax - adc rdx,0 - mov r11,rdx - mov rax,r13 - mul rbx - add r11,rax - adc rdx,0 - mov r12,rdx - mov rax,r14 - mul rbx - add r12,rax - adc rdx,0 - mov r13,rdx - mov rax,r15 - mul rbx - add r13,rax - adc rdx,0 - mov r14,rdx - mov rax,r8 - mul rbx - add r14,rax - adc rdx,0 - mov r15,rdx - mov rax,r9 - mul rbx - add r15,rax - adc rdx,0 - mov rsi,rdx - - mov QWORD[536+rsp],r10 - - - - - - mov rbx,QWORD[8+rcx] - - mov rax,QWORD[16+rcx] - mul rbx - add r11,rax - adc rdx,0 - mov QWORD[544+rsp],r11 - - mov r10,rdx - mov rax,QWORD[24+rcx] - mul rbx - add r12,rax - adc rdx,0 - add r12,r10 - adc rdx,0 - mov QWORD[552+rsp],r12 - - mov r10,rdx - mov rax,QWORD[32+rcx] - mul rbx - add r13,rax - adc rdx,0 - add r13,r10 - adc rdx,0 - - mov r10,rdx - mov rax,QWORD[40+rcx] - mul rbx - add r14,rax - adc rdx,0 - add r14,r10 - adc rdx,0 - - mov r10,rdx - mov rax,r8 - mul rbx - add r15,rax - adc rdx,0 - add r15,r10 - adc rdx,0 - - mov r10,rdx - mov rax,r9 - mul rbx - add rsi,rax - adc rdx,0 - add rsi,r10 - adc rdx,0 - - mov r11,rdx - - - - - mov rbx,QWORD[16+rcx] - - mov rax,QWORD[24+rcx] - mul rbx - add r13,rax - adc rdx,0 - mov QWORD[560+rsp],r13 - - mov r10,rdx - mov rax,QWORD[32+rcx] - mul rbx - add r14,rax - adc rdx,0 - add r14,r10 - adc rdx,0 - mov QWORD[568+rsp],r14 - - mov r10,rdx - mov rax,QWORD[40+rcx] - mul rbx - add r15,rax - adc rdx,0 - add r15,r10 - adc rdx,0 - - mov r10,rdx - mov rax,r8 - mul rbx - add rsi,rax - adc rdx,0 - add rsi,r10 - adc rdx,0 - - mov r10,rdx - mov rax,r9 - mul rbx - add r11,rax - adc rdx,0 - add r11,r10 - adc rdx,0 - - mov r12,rdx - - - - - - mov rbx,QWORD[24+rcx] - - mov rax,QWORD[32+rcx] - mul rbx - add r15,rax - adc rdx,0 - mov QWORD[576+rsp],r15 - - mov r10,rdx - mov rax,QWORD[40+rcx] - mul rbx - add rsi,rax - adc rdx,0 - add rsi,r10 - adc rdx,0 - mov QWORD[584+rsp],rsi - - mov r10,rdx - mov rax,r8 - mul rbx - add r11,rax - adc rdx,0 - add r11,r10 - adc rdx,0 - - mov r10,rdx - mov rax,r9 - mul rbx - add r12,rax - adc rdx,0 - add r12,r10 - adc rdx,0 - - mov r15,rdx - - - - - mov rbx,QWORD[32+rcx] - - mov rax,QWORD[40+rcx] - mul rbx - add r11,rax - adc rdx,0 - mov QWORD[592+rsp],r11 - - mov r10,rdx - mov rax,r8 - mul rbx - add r12,rax - adc rdx,0 - add r12,r10 - adc rdx,0 - mov QWORD[600+rsp],r12 - - mov r10,rdx - mov rax,r9 - mul rbx - add r15,rax - adc rdx,0 - add r15,r10 - adc rdx,0 - - mov r11,rdx - - - - - mov rbx,QWORD[40+rcx] - - mov rax,r8 - mul rbx - add r15,rax - adc rdx,0 - mov QWORD[608+rsp],r15 - - mov r10,rdx - mov rax,r9 - mul rbx - add r11,rax - adc rdx,0 - add r11,r10 - adc rdx,0 - mov QWORD[616+rsp],r11 - - mov r12,rdx - - - - - mov rbx,r8 - - mov rax,r9 - mul rbx - add r12,rax - adc rdx,0 - mov QWORD[624+rsp],r12 - - mov QWORD[632+rsp],rdx - - - mov r10,QWORD[528+rsp] - mov r11,QWORD[536+rsp] - mov r12,QWORD[544+rsp] - mov r13,QWORD[552+rsp] - mov r14,QWORD[560+rsp] - mov r15,QWORD[568+rsp] - - mov rax,QWORD[24+rcx] - mul rax - mov rdi,rax - mov r8,rdx - - add r10,r10 - adc r11,r11 - adc r12,r12 - adc r13,r13 - adc r14,r14 - adc r15,r15 - adc r8,0 - - mov rax,QWORD[rcx] - mul rax - mov QWORD[520+rsp],rax - mov rbx,rdx - - mov rax,QWORD[8+rcx] - mul rax - - add r10,rbx - adc r11,rax - adc rdx,0 - - mov rbx,rdx - mov QWORD[528+rsp],r10 - mov QWORD[536+rsp],r11 - - mov rax,QWORD[16+rcx] - mul rax - - add r12,rbx - adc r13,rax - adc rdx,0 - - mov rbx,rdx - - mov QWORD[544+rsp],r12 - mov QWORD[552+rsp],r13 - - xor rbp,rbp - add r14,rbx - adc r15,rdi - adc rbp,0 - - mov QWORD[560+rsp],r14 - mov QWORD[568+rsp],r15 - - - - - mov r10,QWORD[576+rsp] - mov r11,QWORD[584+rsp] - mov r12,QWORD[592+rsp] - mov r13,QWORD[600+rsp] - mov r14,QWORD[608+rsp] - mov r15,QWORD[616+rsp] - mov rdi,QWORD[624+rsp] - mov rsi,QWORD[632+rsp] - - mov rax,r9 - mul rax - mov r9,rax - mov rbx,rdx - - add r10,r10 - adc r11,r11 - adc r12,r12 - adc r13,r13 - adc r14,r14 - adc r15,r15 - adc rdi,rdi - adc rsi,rsi - adc rbx,0 - - add r10,rbp - - mov rax,QWORD[32+rcx] - mul rax - - add r10,r8 - adc r11,rax - adc rdx,0 - - mov rbp,rdx - - mov QWORD[576+rsp],r10 - mov QWORD[584+rsp],r11 - - mov rax,QWORD[40+rcx] - mul rax - - add r12,rbp - adc r13,rax - adc rdx,0 - - mov rbp,rdx - - mov QWORD[592+rsp],r12 - mov QWORD[600+rsp],r13 - - mov rax,QWORD[48+rcx] - mul rax - - add r14,rbp - adc r15,rax - adc rdx,0 - - mov QWORD[608+rsp],r14 - mov QWORD[616+rsp],r15 - - add rdi,rdx - adc rsi,r9 - adc rbx,0 - - mov QWORD[624+rsp],rdi - mov QWORD[632+rsp],rsi - mov QWORD[640+rsp],rbx - - jmp NEAR mont_reduce - - - -global mod_exp_512 - -mod_exp_512: - mov QWORD[8+rsp],rdi ;WIN64 prologue - mov QWORD[16+rsp],rsi - mov rax,rsp -$L$SEH_begin_mod_exp_512: - mov rdi,rcx - mov rsi,rdx - mov rdx,r8 - mov rcx,r9 - - - push rbp - push rbx - push r12 - push r13 - push r14 - push r15 - - - mov r8,rsp - sub rsp,2688 - and rsp,-64 - - - mov QWORD[rsp],r8 - mov QWORD[8+rsp],rdi - mov QWORD[16+rsp],rsi - mov QWORD[24+rsp],rcx -$L$body: - - - - pxor xmm4,xmm4 - movdqu xmm0,XMMWORD[rsi] - movdqu xmm1,XMMWORD[16+rsi] - movdqu xmm2,XMMWORD[32+rsi] - movdqu xmm3,XMMWORD[48+rsi] - movdqa XMMWORD[512+rsp],xmm4 - movdqa XMMWORD[528+rsp],xmm4 - movdqa XMMWORD[608+rsp],xmm4 - movdqa XMMWORD[624+rsp],xmm4 - movdqa XMMWORD[544+rsp],xmm0 - movdqa XMMWORD[560+rsp],xmm1 - movdqa XMMWORD[576+rsp],xmm2 - movdqa XMMWORD[592+rsp],xmm3 - - - movdqu xmm0,XMMWORD[rdx] - movdqu xmm1,XMMWORD[16+rdx] - movdqu xmm2,XMMWORD[32+rdx] - movdqu xmm3,XMMWORD[48+rdx] - - lea rbx,[384+rsp] - mov QWORD[136+rsp],rbx - call mont_reduce - - - lea rcx,[448+rsp] - xor rax,rax - mov QWORD[rcx],rax - mov QWORD[8+rcx],rax - mov QWORD[24+rcx],rax - mov QWORD[32+rcx],rax - mov QWORD[40+rcx],rax - mov QWORD[48+rcx],rax - mov QWORD[56+rcx],rax - mov QWORD[128+rsp],rax - mov QWORD[16+rcx],1 - - lea rbp,[640+rsp] - mov rsi,rcx - mov rdi,rbp - mov rax,8 -loop_0: - mov rbx,QWORD[rcx] - mov WORD[rdi],bx - shr rbx,16 - mov WORD[64+rdi],bx - shr rbx,16 - mov WORD[128+rdi],bx - shr rbx,16 - mov WORD[192+rdi],bx - lea rcx,[8+rcx] - lea rdi,[256+rdi] - dec rax - jnz NEAR loop_0 - mov rax,31 - mov QWORD[32+rsp],rax - mov QWORD[40+rsp],rbp - - mov QWORD[136+rsp],rsi - mov r10,QWORD[rsi] - mov r11,QWORD[8+rsi] - mov r12,QWORD[16+rsi] - mov r13,QWORD[24+rsi] - mov r14,QWORD[32+rsi] - mov r15,QWORD[40+rsi] - mov r8,QWORD[48+rsi] - mov r9,QWORD[56+rsi] -init_loop: - lea rdi,[384+rsp] - call mont_mul_a3b - lea rsi,[448+rsp] - mov rbp,QWORD[40+rsp] - add rbp,2 - mov QWORD[40+rsp],rbp - mov rcx,rsi - mov rax,8 -loop_1: - mov rbx,QWORD[rcx] - mov WORD[rbp],bx - shr rbx,16 - mov WORD[64+rbp],bx - shr rbx,16 - mov WORD[128+rbp],bx - shr rbx,16 - mov WORD[192+rbp],bx - lea rcx,[8+rcx] - lea rbp,[256+rbp] - dec rax - jnz NEAR loop_1 - mov rax,QWORD[32+rsp] - sub rax,1 - mov QWORD[32+rsp],rax - jne NEAR init_loop - - - - movdqa XMMWORD[64+rsp],xmm0 - movdqa XMMWORD[80+rsp],xmm1 - movdqa XMMWORD[96+rsp],xmm2 - movdqa XMMWORD[112+rsp],xmm3 - - - - - - mov eax,DWORD[126+rsp] - mov rdx,rax - shr rax,11 - and edx,0x07FF - mov DWORD[126+rsp],edx - lea rsi,[640+rax*2+rsp] - mov rdx,QWORD[8+rsp] - mov rbp,4 -loop_2: - movzx rbx,WORD[192+rsi] - movzx rax,WORD[448+rsi] - shl rbx,16 - shl rax,16 - mov bx,WORD[128+rsi] - mov ax,WORD[384+rsi] - shl rbx,16 - shl rax,16 - mov bx,WORD[64+rsi] - mov ax,WORD[320+rsi] - shl rbx,16 - shl rax,16 - mov bx,WORD[rsi] - mov ax,WORD[256+rsi] - mov QWORD[rdx],rbx - mov QWORD[8+rdx],rax - lea rsi,[512+rsi] - lea rdx,[16+rdx] - sub rbp,1 - jnz NEAR loop_2 - mov QWORD[48+rsp],505 - - mov rcx,QWORD[8+rsp] - mov QWORD[136+rsp],rcx - mov r10,QWORD[rcx] - mov r11,QWORD[8+rcx] - mov r12,QWORD[16+rcx] - mov r13,QWORD[24+rcx] - mov r14,QWORD[32+rcx] - mov r15,QWORD[40+rcx] - mov r8,QWORD[48+rcx] - mov r9,QWORD[56+rcx] - jmp NEAR sqr_2 - -main_loop_a3b: - call sqr_reduce - call sqr_reduce - call sqr_reduce -sqr_2: - call sqr_reduce - call sqr_reduce - - - - mov rcx,QWORD[48+rsp] - mov rax,rcx - shr rax,4 - mov edx,DWORD[64+rax*2+rsp] - and rcx,15 - shr rdx,cl - and rdx,0x1F - - lea rsi,[640+rdx*2+rsp] - lea rdx,[448+rsp] - mov rdi,rdx - mov rbp,4 -loop_3: - movzx rbx,WORD[192+rsi] - movzx rax,WORD[448+rsi] - shl rbx,16 - shl rax,16 - mov bx,WORD[128+rsi] - mov ax,WORD[384+rsi] - shl rbx,16 - shl rax,16 - mov bx,WORD[64+rsi] - mov ax,WORD[320+rsi] - shl rbx,16 - shl rax,16 - mov bx,WORD[rsi] - mov ax,WORD[256+rsi] - mov QWORD[rdx],rbx - mov QWORD[8+rdx],rax - lea rsi,[512+rsi] - lea rdx,[16+rdx] - sub rbp,1 - jnz NEAR loop_3 - mov rsi,QWORD[8+rsp] - call mont_mul_a3b - - - - mov rcx,QWORD[48+rsp] - sub rcx,5 - mov QWORD[48+rsp],rcx - jge NEAR main_loop_a3b - - - -end_main_loop_a3b: - - - mov rdx,QWORD[8+rsp] - pxor xmm4,xmm4 - movdqu xmm0,XMMWORD[rdx] - movdqu xmm1,XMMWORD[16+rdx] - movdqu xmm2,XMMWORD[32+rdx] - movdqu xmm3,XMMWORD[48+rdx] - movdqa XMMWORD[576+rsp],xmm4 - movdqa XMMWORD[592+rsp],xmm4 - movdqa XMMWORD[608+rsp],xmm4 - movdqa XMMWORD[624+rsp],xmm4 - movdqa XMMWORD[512+rsp],xmm0 - movdqa XMMWORD[528+rsp],xmm1 - movdqa XMMWORD[544+rsp],xmm2 - movdqa XMMWORD[560+rsp],xmm3 - call mont_reduce - - - - mov rax,QWORD[8+rsp] - mov r8,QWORD[rax] - mov r9,QWORD[8+rax] - mov r10,QWORD[16+rax] - mov r11,QWORD[24+rax] - mov r12,QWORD[32+rax] - mov r13,QWORD[40+rax] - mov r14,QWORD[48+rax] - mov r15,QWORD[56+rax] - - - mov rbx,QWORD[24+rsp] - add rbx,512 - - sub r8,QWORD[rbx] - sbb r9,QWORD[8+rbx] - sbb r10,QWORD[16+rbx] - sbb r11,QWORD[24+rbx] - sbb r12,QWORD[32+rbx] - sbb r13,QWORD[40+rbx] - sbb r14,QWORD[48+rbx] - sbb r15,QWORD[56+rbx] - - - mov rsi,QWORD[rax] - mov rdi,QWORD[8+rax] - mov rcx,QWORD[16+rax] - mov rdx,QWORD[24+rax] - cmovnc rsi,r8 - cmovnc rdi,r9 - cmovnc rcx,r10 - cmovnc rdx,r11 - mov QWORD[rax],rsi - mov QWORD[8+rax],rdi - mov QWORD[16+rax],rcx - mov QWORD[24+rax],rdx - - mov rsi,QWORD[32+rax] - mov rdi,QWORD[40+rax] - mov rcx,QWORD[48+rax] - mov rdx,QWORD[56+rax] - cmovnc rsi,r12 - cmovnc rdi,r13 - cmovnc rcx,r14 - cmovnc rdx,r15 - mov QWORD[32+rax],rsi - mov QWORD[40+rax],rdi - mov QWORD[48+rax],rcx - mov QWORD[56+rax],rdx - - mov rsi,QWORD[rsp] - mov r15,QWORD[rsi] - mov r14,QWORD[8+rsi] - mov r13,QWORD[16+rsi] - mov r12,QWORD[24+rsi] - mov rbx,QWORD[32+rsi] - mov rbp,QWORD[40+rsi] - lea rsp,[48+rsi] -$L$epilogue: - mov rdi,QWORD[8+rsp] ;WIN64 epilogue - mov rsi,QWORD[16+rsp] - DB 0F3h,0C3h ;repret -$L$SEH_end_mod_exp_512: -EXTERN __imp_RtlVirtualUnwind - -ALIGN 16 -mod_exp_512_se_handler: - push rsi - push rdi - push rbx - push rbp - push r12 - push r13 - push r14 - push r15 - pushfq - sub rsp,64 - - mov rax,QWORD[120+r8] - mov rbx,QWORD[248+r8] - - lea r10,[$L$body] - cmp rbx,r10 - jb NEAR $L$in_prologue - - mov rax,QWORD[152+r8] - - lea r10,[$L$epilogue] - cmp rbx,r10 - jae NEAR $L$in_prologue - - mov rax,QWORD[rax] - - mov rbx,QWORD[32+rax] - mov rbp,QWORD[40+rax] - mov r12,QWORD[24+rax] - mov r13,QWORD[16+rax] - mov r14,QWORD[8+rax] - mov r15,QWORD[rax] - lea rax,[48+rax] - mov QWORD[144+r8],rbx - mov QWORD[160+r8],rbp - mov QWORD[216+r8],r12 - mov QWORD[224+r8],r13 - mov QWORD[232+r8],r14 - mov QWORD[240+r8],r15 - -$L$in_prologue: - mov rdi,QWORD[8+rax] - mov rsi,QWORD[16+rax] - mov QWORD[152+r8],rax - mov QWORD[168+r8],rsi - mov QWORD[176+r8],rdi - - mov rdi,QWORD[40+r9] - mov rsi,r8 - mov ecx,154 - DD 0xa548f3fc - - mov rsi,r9 - xor rcx,rcx - mov rdx,QWORD[8+rsi] - mov r8,QWORD[rsi] - mov r9,QWORD[16+rsi] - mov r10,QWORD[40+rsi] - lea r11,[56+rsi] - lea r12,[24+rsi] - mov QWORD[32+rsp],r10 - mov QWORD[40+rsp],r11 - mov QWORD[48+rsp],r12 - mov QWORD[56+rsp],rcx - call QWORD[__imp_RtlVirtualUnwind] - - mov eax,1 - add rsp,64 - popfq - pop r15 - pop r14 - pop r13 - pop r12 - pop rbp - pop rbx - pop rdi - pop rsi - DB 0F3h,0C3h ;repret - - -section .pdata rdata align=4 -ALIGN 4 - DD $L$SEH_begin_mod_exp_512 wrt ..imagebase - DD $L$SEH_end_mod_exp_512 wrt ..imagebase - DD $L$SEH_info_mod_exp_512 wrt ..imagebase - -section .xdata rdata align=8 -ALIGN 8 -$L$SEH_info_mod_exp_512: -DB 9,0,0,0 - DD mod_exp_512_se_handler wrt ..imagebase
diff --git a/third_party/bspatch/BUILD.gn b/third_party/bspatch/BUILD.gn new file mode 100644 index 0000000..3929615 --- /dev/null +++ b/third_party/bspatch/BUILD.gn
@@ -0,0 +1,17 @@ +# Copyright 2015 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. + +source_set("bspatch") { + sources = [ + "mbspatch.cc", + "mbspatch.h", + ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] + + deps = [ + "//third_party/lzma_sdk", + ] +}
diff --git a/third_party/khronos/DEPS b/third_party/khronos/DEPS index 63aa5d9..971f63f7 100644 --- a/third_party/khronos/DEPS +++ b/third_party/khronos/DEPS
@@ -1,4 +1,4 @@ include_rules = [ - "+mojo/public/c/gles2/gles2_export.h", "+gpu/command_buffer/client/gles2_c_lib_export.h", + "+third_party/mojo/src/mojo/public/c/gles2/gles2_export.h", ]
diff --git a/third_party/khronos/KHR/khrplatform.h b/third_party/khronos/KHR/khrplatform.h index ee062de..026c9c7e 100644 --- a/third_party/khronos/KHR/khrplatform.h +++ b/third_party/khronos/KHR/khrplatform.h
@@ -124,7 +124,7 @@ #undef KHRONOS_APICALL #if defined(GLES2_USE_MOJO) -#include "mojo/public/c/gles2/gles2_export.h" +#include "third_party/mojo/src/mojo/public/c/gles2/gles2_export.h" #define KHRONOS_APICALL MOJO_GLES2_EXPORT #else #include "gpu/command_buffer/client/gles2_c_lib_export.h"
diff --git a/third_party/libjingle/BUILD.gn b/third_party/libjingle/BUILD.gn index 32877f7..6357b92 100644 --- a/third_party/libjingle/BUILD.gn +++ b/third_party/libjingle/BUILD.gn
@@ -260,7 +260,7 @@ ":jingle_deps", ] deps = [ - "//third_party/webrtc/base:webrtc_base", + "//third_party/webrtc/base:rtc_base", ":libjingle_p2p_constants", ]
diff --git a/third_party/libjingle/README.chromium b/third_party/libjingle/README.chromium index 908e75e4..89e2d1b2 100644 --- a/third_party/libjingle/README.chromium +++ b/third_party/libjingle/README.chromium
@@ -1,7 +1,7 @@ Name: libjingle URL: http://code.google.com/p/webrtc/ Version: unknown -Revision: 8128 +Revision: 8141 License: BSD License File: source/talk/COPYING Security Critical: yes
diff --git a/third_party/libwebp/README.chromium b/third_party/libwebp/README.chromium index bdc4fdb..d15c9ad 100644 --- a/third_party/libwebp/README.chromium +++ b/third_party/libwebp/README.chromium
@@ -24,3 +24,4 @@ Revert patch f7fc4bc: dec/webp.c: don't wait for data before reporting w/h 6638710 webp/types.h: use inline for clang++/-std=c++11 a3946b8 enc_neon: fix building with non-Xcode clang (iOS) + 783a8cd Regression fix for lossless decoding
diff --git a/third_party/libwebp/dec/vp8l.c b/third_party/libwebp/dec/vp8l.c index a7e7e25..e2780e5b 100644 --- a/third_party/libwebp/dec/vp8l.c +++ b/third_party/libwebp/dec/vp8l.c
@@ -900,7 +900,7 @@ process_func(dec, row); } } - if (src < src_last) { + if (src < src_end) { if (col & mask) htree_group = GetHtreeGroupForPos(hdr, col, row); if (color_cache != NULL) { while (last_cached < src) {
diff --git a/third_party/mojo/src/mojo/edk/system/message_pipe_dispatcher_unittest.cc b/third_party/mojo/src/mojo/edk/system/message_pipe_dispatcher_unittest.cc index b5562b0..2f97b29 100644 --- a/third_party/mojo/src/mojo/edk/system/message_pipe_dispatcher_unittest.cc +++ b/third_party/mojo/src/mojo/edk/system/message_pipe_dispatcher_unittest.cc
@@ -340,13 +340,8 @@ } } -#if defined(OS_WIN) // http://crbug.com/396386 -#define MAYBE_BasicThreaded DISABLED_BasicThreaded -#else -#define MAYBE_BasicThreaded BasicThreaded -#endif -TEST(MessagePipeDispatcherTest, MAYBE_BasicThreaded) { +TEST(MessagePipeDispatcherTest, DISABLED_BasicThreaded) { test::Stopwatch stopwatch; int32_t buffer[1]; const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer));
diff --git a/third_party/mojo/src/mojo/edk/system/simple_dispatcher_unittest.cc b/third_party/mojo/src/mojo/edk/system/simple_dispatcher_unittest.cc index b8e57e9..7d5edcb 100644 --- a/third_party/mojo/src/mojo/edk/system/simple_dispatcher_unittest.cc +++ b/third_party/mojo/src/mojo/edk/system/simple_dispatcher_unittest.cc
@@ -325,13 +325,8 @@ // Don't need to remove waiters from closed dispatchers. } -#if defined(OS_WIN) // http://crbug.com/396393 -#define MAYBE_BasicThreaded DISABLED_BasicThreaded -#else -#define MAYBE_BasicThreaded BasicThreaded -#endif -TEST(SimpleDispatcherTest, MAYBE_BasicThreaded) { +TEST(SimpleDispatcherTest, DISABLED_BasicThreaded) { test::Stopwatch stopwatch; bool did_wait; MojoResult result;
diff --git a/third_party/qcms/README.chromium b/third_party/qcms/README.chromium index fa05726..fdf3394 100644 --- a/third_party/qcms/README.chromium +++ b/third_party/qcms/README.chromium
@@ -47,6 +47,8 @@ - https://code.google.com/p/chromium/issues/detail?id=401971 - [APPLE port] Use en-localized profile description names - https://code.google.com/p/chromium/issues/detail?id=401971 + - [APPLE port] Use mmod data for profile descriptions + - https://code.google.com/p/chromium/issues/detail?id=401971 - Minor variable name change: description -> description_offset - https://code.google.com/p/chromium/issues/detail?id=401971 To regenerate google.patch:
diff --git a/third_party/qcms/src/iccread.c b/third_party/qcms/src/iccread.c index 5635938..6cec34a3 100644 --- a/third_party/qcms/src/iccread.c +++ b/third_party/qcms/src/iccread.c
@@ -356,6 +356,7 @@ #define DESC_TYPE 0x64657363 // 'desc' #define MLUC_TYPE 0x6d6c7563 // 'mluc' +#define MMOD_TYPE 0x6D6D6F64 // 'mmod' static bool read_tag_descType(qcms_profile *profile, struct mem_source *src, struct tag_index index, uint32_t tag_id) { @@ -405,9 +406,10 @@ #if defined(__APPLE__) +// Use the dscm tag to change profile description "Display" to its more specific en-localized monitor name, if any. + #define TAG_dscm 0x6473636D // 'dscm' -// Use dscm tag to change profile description "Display" to its more specific en-localized monitor name, if any. static bool read_tag_dscmType(qcms_profile *profile, struct mem_source *src, struct tag_index index, uint32_t tag_id) { if (strcmp(profile->description, "Display") != 0) @@ -462,6 +464,40 @@ return false; } +// Use the mmod tag to change profile description "Display" to its specific mmod maker model data, if any. + +#define TAG_mmod 0x6D6D6F64 // 'mmod' + +static bool read_tag_mmodType(qcms_profile *profile, struct mem_source *src, struct tag_index index, uint32_t tag_id) +{ + if (strcmp(profile->description, "Display") != 0) + return true; + + struct tag *tag = find_tag(index, tag_id); + if (tag) { + const uint8_t length = 4 * 4; // Four 4-byte fields: 'mmod', 0, maker, model. + + uint32_t offset = tag->offset; + if (tag->size < 40 || read_u32(src, offset) != MMOD_TYPE) + goto invalid_mmod_tag; + + for (uint8_t i = 0; i < length; ++i) { + uint8_t value = read_u8(src, offset + i); + if (!src->valid) + goto invalid_mmod_tag; + profile->description[i] = value ? value : '.'; + } + profile->description[length] = 0; + } + + if (src->valid) + return true; + +invalid_mmod_tag: + invalid_source(src, "invalid mmod tag"); + return false; +} + #endif // __APPLE__ #define XYZ_TYPE 0x58595a20 // 'XYZ ' @@ -1163,6 +1199,8 @@ #if defined(__APPLE__) if (!read_tag_dscmType(profile, src, index, TAG_dscm)) goto invalid_tag_table; + if (!read_tag_mmodType(profile, src, index, TAG_mmod)) + goto invalid_tag_table; #endif // __APPLE__ if (find_tag(index, TAG_CHAD)) {
diff --git a/tools/android/asan/asan_device_setup.sh b/tools/android/asan/asan_device_setup.sh deleted file mode 100755 index 5948f2b..0000000 --- a/tools/android/asan/asan_device_setup.sh +++ /dev/null
@@ -1,194 +0,0 @@ -#!/bin/bash -e -#===- lib/asan/scripts/asan_device_setup.py -----------------------------------===# -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -# Prepare Android device to run ASan applications. -# -#===------------------------------------------------------------------------===# - - -HERE="$(cd "$(dirname "$0")" && pwd)" - -revert=no -extra_options= -device= -lib= - -function usage { - echo "usage: $0 [--revert] [--device device-id] [--lib path] [--extra_options options]" - echo " --revert: Uninstall ASan from the device." - echo " --lib: Path to ASan runtime library." - echo " --extra_options: Extra ASAN_OPTIONS." - echo " --device: Install to the given device. Use 'adb devices' to find" - echo " device-id." - echo - exit 1 -} - -while [[ $# > 0 ]]; do - case $1 in - --revert) - revert=yes - ;; - --extra-options) - shift - if [[ $# == 0 ]]; then - echo "--extra-options requires an argument." - exit 1 - fi - extra_options="$1" - ;; - --lib) - shift - if [[ $# == 0 ]]; then - echo "--lib requires an argument." - exit 1 - fi - lib="$1" - ;; - --device) - shift - if [[ $# == 0 ]]; then - echo "--device requires an argument." - exit 1 - fi - device="$1" - ;; - *) - usage - ;; - esac - shift -done - -ADB=${ADB:-adb} -if [[ x$device != x ]]; then - ADB="$ADB -s $device" -fi - -ASAN_RT="libclang_rt.asan-arm-android.so" - -if [[ x$revert == xyes ]]; then - echo '>> Uninstalling ASan' - $ADB root - $ADB wait-for-device - $ADB remount - $ADB shell mv /system/bin/app_process.real /system/bin/app_process - $ADB shell rm /system/bin/asanwrapper - $ADB shell rm /system/lib/$ASAN_RT - - echo '>> Restarting shell' - $ADB shell stop - $ADB shell start - - echo '>> Done' - exit 0 -fi - -if [[ -d "$lib" ]]; then - ASAN_RT_PATH="$lib" -elif [[ -f "$lib" && "$lib" == *"$ASAN_RT" ]]; then - ASAN_RT_PATH=$(dirname "$lib") -elif [[ -f "$HERE/$ASAN_RT" ]]; then - ASAN_RT_PATH="$HERE" -elif [[ $(basename "$HERE") == "bin" ]]; then - # We could be in the toolchain's base directory. - # Consider ../lib and ../lib/clang/$VERSION/lib/linux. - P=$(ls "$HERE"/../lib/"$ASAN_RT" "$HERE"/../lib/clang/*/lib/linux/"$ASAN_RT" 2>/dev/null | sort | tail -1) - if [[ -n "$P" ]]; then - ASAN_RT_PATH="$(dirname "$P")" - fi -fi - -if [[ -z "$ASAN_RT_PATH" || ! -f "$ASAN_RT_PATH/$ASAN_RT" ]]; then - echo "ASan runtime library not found" - exit 1 -fi - -TMPDIRBASE=$(mktemp -d) -TMPDIROLD="$TMPDIRBASE/old" -TMPDIR="$TMPDIRBASE/new" -mkdir "$TMPDIROLD" - -echo '>> Remounting /system rw' -$ADB root -$ADB wait-for-device -$ADB remount - -echo '>> Copying files from the device' -$ADB pull /system/bin/app_process "$TMPDIROLD" -$ADB pull /system/bin/app_process.real "$TMPDIROLD" || true -$ADB pull /system/bin/asanwrapper "$TMPDIROLD" || true -$ADB pull /system/lib/libclang_rt.asan-arm-android.so "$TMPDIROLD" || true -cp -r "$TMPDIROLD" "$TMPDIR" - -if ! [[ -f "$TMPDIR/app_process" ]]; then - echo "app_process missing???" - exit 1 -fi - -if [[ -f "$TMPDIR/app_process.real" ]]; then - echo "app_process.real exists, updating the wrapper" -else - echo "app_process.real missing, new installation" - mv "$TMPDIR/app_process" "$TMPDIR/app_process.real" -fi - -echo '>> Generating wrappers' - -cp "$ASAN_RT_PATH/$ASAN_RT" "$TMPDIR/" - -# FIXME: alloc_dealloc_mismatch=0 prevents a failure in libdvm startup, -# which may or may not be a real bug (probably not). -ASAN_OPTIONS=start_deactivated=1,alloc_dealloc_mismatch=0 -if [[ x$extra_options != x ]] ; then - ASAN_OPTIONS="$ASAN_OPTIONS,$extra_options" -fi - -# Zygote wrapper. -cat <<EOF >"$TMPDIR/app_process" -#!/system/bin/sh -ASAN_OPTIONS=$ASAN_OPTIONS \\ -LD_PRELOAD=libclang_rt.asan-arm-android.so \\ -exec /system/bin/app_process.real \$@ - -EOF - -# General command-line tool wrapper (use for anything that's not started as -# zygote). -cat <<EOF >"$TMPDIR/asanwrapper" -#!/system/bin/sh -LD_PRELOAD=libclang_rt.asan-arm-android.so \\ -exec \$@ - -EOF - -if ! ( cd "$TMPDIRBASE" && diff -qr old/ new/ ) ; then - echo '>> Pushing files to the device' - $ADB push "$TMPDIR/$ASAN_RT" /system/lib/ - $ADB push "$TMPDIR/app_process" /system/bin/app_process - $ADB push "$TMPDIR/app_process.real" /system/bin/app_process.real - $ADB push "$TMPDIR/asanwrapper" /system/bin/asanwrapper - $ADB shell chown root.shell \ - /system/bin/app_process \ - /system/bin/app_process.real \ - /system/bin/asanwrapper - $ADB shell chmod 755 \ - /system/bin/app_process \ - /system/bin/app_process.real \ - /system/bin/asanwrapper - - echo '>> Restarting shell (asynchronous)' - $ADB shell stop - $ADB shell start - - echo '>> Please wait until the device restarts' -else - echo '>> Device is up to date' -fi - -rm -r "$TMPDIRBASE"
diff --git a/tools/android/asan/third_party/README.chromium b/tools/android/asan/third_party/README.chromium new file mode 100644 index 0000000..5689608c --- /dev/null +++ b/tools/android/asan/third_party/README.chromium
@@ -0,0 +1,7 @@ +Name: asan_device_setup.sh +License: University of Illinois Open Source License. +Version: 226816 +URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/scripts/asan_device_setup?view=co +Security Critical: no + +asan_device_setup.sh is a verbatim copy of asan_device_setup in the LLVM trunk.
diff --git a/tools/android/asan/third_party/asan_device_setup.sh b/tools/android/asan/third_party/asan_device_setup.sh new file mode 100755 index 0000000..eb50ea4ed --- /dev/null +++ b/tools/android/asan/third_party/asan_device_setup.sh
@@ -0,0 +1,267 @@ +#!/bin/bash +#===- lib/asan/scripts/asan_device_setup -----------------------------------===# +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +# Prepare Android device to run ASan applications. +# +#===------------------------------------------------------------------------===# + +set -e + +HERE="$(cd "$(dirname "$0")" && pwd)" + +revert=no +extra_options= +device= +lib= + +function usage { + echo "usage: $0 [--revert] [--device device-id] [--lib path] [--extra-options options]" + echo " --revert: Uninstall ASan from the device." + echo " --lib: Path to ASan runtime library." + echo " --extra-options: Extra ASAN_OPTIONS." + echo " --device: Install to the given device. Use 'adb devices' to find" + echo " device-id." + echo + exit 1 +} + +function get_device_arch { # OUTVAR + local _outvar=$1 + local _ABI=$($ADB shell getprop ro.product.cpu.abi) + local _ARCH= + if [[ $_ABI == x86* ]]; then + _ARCH=i686 + elif [[ $_ABI == armeabi* ]]; then + _ARCH=arm + else + echo "Unrecognized device ABI: $_ABI" + exit 1 + fi + eval $_outvar=\$_ARCH +} + +while [[ $# > 0 ]]; do + case $1 in + --revert) + revert=yes + ;; + --extra-options) + shift + if [[ $# == 0 ]]; then + echo "--extra-options requires an argument." + exit 1 + fi + extra_options="$1" + ;; + --lib) + shift + if [[ $# == 0 ]]; then + echo "--lib requires an argument." + exit 1 + fi + lib="$1" + ;; + --device) + shift + if [[ $# == 0 ]]; then + echo "--device requires an argument." + exit 1 + fi + device="$1" + ;; + *) + usage + ;; + esac + shift +done + +ADB=${ADB:-adb} +if [[ x$device != x ]]; then + ADB="$ADB -s $device" +fi + +echo '>> Remounting /system rw' +$ADB root +$ADB wait-for-device +$ADB remount +$ADB wait-for-device + +get_device_arch ARCH +echo "Target architecture: $ARCH" +ASAN_RT="libclang_rt.asan-$ARCH-android.so" + +if [[ x$revert == xyes ]]; then + echo '>> Uninstalling ASan' + + if ! $ADB shell readlink /system/bin/app_process | grep 'app_process' >&/dev/null; then + echo '>> Pre-L device detected.' + $ADB shell mv /system/bin/app_process.real /system/bin/app_process + $ADB shell rm /system/bin/asanwrapper + $ADB shell rm /system/lib/$ASAN_RT + else + $ADB shell rm /system/bin/app_process.wrap + $ADB shell rm /system/bin/asanwrapper + $ADB shell rm /system/lib/$ASAN_RT + $ADB shell rm /system/bin/app_process + $ADB shell ln -s /system/bin/app_process32 /system/bin/app_process + fi + + echo '>> Restarting shell' + $ADB shell stop + $ADB shell start + + echo '>> Done' + exit 0 +fi + +if [[ -d "$lib" ]]; then + ASAN_RT_PATH="$lib" +elif [[ -f "$lib" && "$lib" == *"$ASAN_RT" ]]; then + ASAN_RT_PATH=$(dirname "$lib") +elif [[ -f "$HERE/$ASAN_RT" ]]; then + ASAN_RT_PATH="$HERE" +elif [[ $(basename "$HERE") == "bin" ]]; then + # We could be in the toolchain's base directory. + # Consider ../lib, ../lib/asan, ../lib/linux and ../lib/clang/$VERSION/lib/linux. + P=$(ls "$HERE"/../lib/"$ASAN_RT" "$HERE"/../lib/asan/"$ASAN_RT" "$HERE"/../lib/linux/"$ASAN_RT" "$HERE"/../lib/clang/*/lib/linux/"$ASAN_RT" 2>/dev/null | sort | tail -1) + if [[ -n "$P" ]]; then + ASAN_RT_PATH="$(dirname "$P")" + fi +fi + +if [[ -z "$ASAN_RT_PATH" || ! -f "$ASAN_RT_PATH/$ASAN_RT" ]]; then + echo ">> ASan runtime library not found" + exit 1 +fi + +TMPDIRBASE=$(mktemp -d) +TMPDIROLD="$TMPDIRBASE/old" +TMPDIR="$TMPDIRBASE/new" +mkdir "$TMPDIROLD" + +RELEASE=$($ADB shell getprop ro.build.version.release) +PRE_L=0 +if echo "$RELEASE" | grep '^4\.' >&/dev/null; then + PRE_L=1 +fi + +if ! $ADB shell readlink /system/bin/app_process | grep 'app_process' >&/dev/null; then + + if $ADB pull /system/bin/app_process.real /dev/null >&/dev/null; then + echo '>> Old-style ASan installation detected. Reverting.' + $ADB shell mv /system/bin/app_process.real /system/bin/app_process + fi + + echo '>> Pre-L device detected. Setting up app_process symlink.' + $ADB shell mv /system/bin/app_process /system/bin/app_process32 + $ADB shell ln -s /system/bin/app_process32 /system/bin/app_process +fi + +echo '>> Copying files from the device' +$ADB pull /system/bin/app_process.wrap "$TMPDIROLD" || true +$ADB pull /system/bin/asanwrapper "$TMPDIROLD" || true +$ADB pull /system/lib/"$ASAN_RT" "$TMPDIROLD" || true +cp -r "$TMPDIROLD" "$TMPDIR" + +if [[ -f "$TMPDIR/app_process.wrap" ]]; then + echo ">> Previous installation detected" +else + echo ">> New installation" +fi + +echo '>> Generating wrappers' + +cp "$ASAN_RT_PATH/$ASAN_RT" "$TMPDIR/" + +# FIXME: alloc_dealloc_mismatch=0 prevents a failure in libdvm startup, +# which may or may not be a real bug (probably not). +ASAN_OPTIONS=start_deactivated=1,alloc_dealloc_mismatch=0 + +# On Android-L not allowing user segv handler breaks some applications. +if [[ PRE_L -eq 0 ]]; then + ASAN_OPTIONS="$ASAN_OPTIONS,allow_user_segv_handler=1" +fi + +if [[ x$extra_options != x ]] ; then + ASAN_OPTIONS="$ASAN_OPTIONS,$extra_options" +fi + +# Zygote wrapper. +cat <<EOF >"$TMPDIR/app_process.wrap" +#!/system/bin/sh-from-zygote +ASAN_OPTIONS=$ASAN_OPTIONS \\ +LD_PRELOAD=\$LD_PRELOAD:$ASAN_RT \\ +exec /system/bin/app_process32 \$@ + +EOF + +# General command-line tool wrapper (use for anything that's not started as +# zygote). +cat <<EOF >"$TMPDIR/asanwrapper" +#!/system/bin/sh +LD_PRELOAD=$ASAN_RT \\ +exec \$@ + +EOF + +if ! ( cd "$TMPDIRBASE" && diff -qr old/ new/ ) ; then + echo '>> Pushing files to the device' + $ADB push "$TMPDIR/$ASAN_RT" /system/lib/ + $ADB push "$TMPDIR/app_process.wrap" /system/bin/app_process.wrap + $ADB push "$TMPDIR/asanwrapper" /system/bin/asanwrapper + + $ADB shell rm /system/bin/app_process + $ADB shell ln -s /system/bin/app_process.wrap /system/bin/app_process + + $ADB shell chown root.shell \ + /system/lib/"$ASAN_RT" \ + /system/bin/app_process.wrap \ + /system/bin/asanwrapper + $ADB shell chmod 644 \ + /system/lib/"$ASAN_RT" + $ADB shell chmod 755 \ + /system/bin/app_process.wrap \ + /system/bin/asanwrapper + + # Make SELinux happy by keeping app_process wrapper and the shell + # it runs on in zygote domain. + ENFORCING=0 + if $ADB shell getenforce | grep Enforcing >/dev/null; then + # Sometimes shell is not allowed to change file contexts. + # Temporarily switch to permissive. + ENFORCING=1 + $ADB shell setenforce 0 + fi + + $ADB shell cp /system/bin/sh /system/bin/sh-from-zygote + + if [[ PRE_L -eq 1 ]]; then + CTX=u:object_r:system_file:s0 + else + CTX=u:object_r:zygote_exec:s0 + fi + $ADB shell chcon $CTX \ + /system/bin/sh-from-zygote \ + /system/bin/app_process.wrap \ + /system/bin/app_process32 + + if [ $ENFORCING == 1 ]; then + $ADB shell setenforce 1 + fi + + echo '>> Restarting shell (asynchronous)' + $ADB shell stop + $ADB shell start + + echo '>> Please wait until the device restarts' +else + echo '>> Device is up to date' +fi + +rm -r "$TMPDIRBASE"
diff --git a/tools/auto_bisect/bisect_perf_regression.py b/tools/auto_bisect/bisect_perf_regression.py index 635adbd..6cd0ebe 100755 --- a/tools/auto_bisect/bisect_perf_regression.py +++ b/tools/auto_bisect/bisect_perf_regression.py
@@ -1318,8 +1318,9 @@ print output if metric and self._IsBisectModeUsingMetric(): - metric_values.append(math_utils.Mean( - _ParseMetricValuesFromOutput(metric, output))) + parsed_metric = _ParseMetricValuesFromOutput(metric, output) + if parsed_metric: + metric_values.append(math_utils.Mean(parsed_metric)) # If we're bisecting on a metric (ie, changes in the mean or # standard deviation) and no metric values are produced, bail out. if not metric_values:
diff --git a/tools/auto_bisect/bisect_perf_regression_test.py b/tools/auto_bisect/bisect_perf_regression_test.py index c10ed78..b71fab6 100644 --- a/tools/auto_bisect/bisect_perf_regression_test.py +++ b/tools/auto_bisect/bisect_perf_regression_test.py
@@ -433,6 +433,7 @@ @mock.patch('bisect_utils.RunGClient') def testSyncToRevisionForChromium(self, mock_RunGClient): bisect_instance = _GetBisectPerformanceMetricsInstance(DEFAULT_OPTIONS) + mock_RunGClient.return_value = 0 bisect_instance._SyncRevision( 'chromium', 'e6db23a037cad47299a94b155b95eebd1ee61a58', 'gclient') expected_params = [
diff --git a/tools/auto_bisect/fetch_build.py b/tools/auto_bisect/fetch_build.py index 4aaee54..ac3f032 100644 --- a/tools/auto_bisect/fetch_build.py +++ b/tools/auto_bisect/fetch_build.py
@@ -30,11 +30,12 @@ # Possible builder types. PERF_BUILDER = 'perf' FULL_BUILDER = 'full' +ANDROID_CHROME_PERF_BUILDER = 'android-chrome-perf' def GetBucketAndRemotePath(revision, builder_type=PERF_BUILDER, target_arch='ia32', target_platform='chromium', - deps_patch_sha=None): + deps_patch_sha=None, extra_src=None): """Returns the location where a build archive is expected to be. Args: @@ -44,12 +45,15 @@ target_platform: Platform name, e.g. "chromium" or "android". deps_patch_sha: SHA1 hash which identifies a particular combination of custom revisions for dependency repositories. + extra_src: Path to a script which can be used to modify the bisect script's + behavior. Returns: A pair of strings (bucket, path), where the archive is expected to be. """ build_archive = BuildArchive.Create( - builder_type, target_arch=target_arch, target_platform=target_platform) + builder_type, target_arch=target_arch, target_platform=target_platform, + extra_src=extra_src) bucket = build_archive.BucketName() remote_path = build_archive.FilePath(revision, deps_patch_sha=deps_patch_sha) return bucket, remote_path @@ -65,14 +69,26 @@ """ @staticmethod - def Create(builder_type, target_arch='ia32', target_platform='chromium'): + def Create(builder_type, target_arch='ia32', target_platform='chromium', + extra_src=None): if builder_type == PERF_BUILDER: return PerfBuildArchive(target_arch, target_platform) if builder_type == FULL_BUILDER: return FullBuildArchive(target_arch, target_platform) + if builder_type == ANDROID_CHROME_PERF_BUILDER: + try: + # Load and initialize a module in extra source file and + # return its module object to access android-chrome specific data. + loaded_extra_src = bisect_utils.LoadExtraSrc(extra_src) + return AndroidChromeBuildArchive( + target_arch, target_platform, loaded_extra_src) + except (IOError, TypeError, ImportError): + raise RuntimeError('Invalid or missing --extra_src. [%s]' % extra_src) raise NotImplementedError('Builder type "%s" not supported.' % builder_type) - def __init__(self, target_arch='ia32', target_platform='chromium'): + def __init__(self, target_arch='ia32', target_platform='chromium', + extra_src=None): + self._extra_src = extra_src if bisect_utils.IsLinuxHost() and target_platform == 'android': self._platform = 'android' elif bisect_utils.IsLinuxHost(): @@ -187,6 +203,43 @@ return platform_to_directory.get(self._platform) +class AndroidChromeBuildArchive(BuildArchive): + """Represents a place where builds of android-chrome type are stored. + + If AndroidChromeBuildArchive is used, it is assumed that the --extra_src + is a valid Python module which contains the module-level functions + GetBucketName and GetArchiveDirectory. + """ + + def BucketName(self): + return self._extra_src.GetBucketName() + + def _ZipFileName(self, revision, deps_patch_sha=None): + """Gets the file name of a zip archive on android-chrome. + + This returns a file name of the form build_product_<revision>.zip, + which is a format used by android-chrome. + + Args: + revision: A git commit hash or other revision string. + deps_patch_sha: SHA1 hash of a DEPS file patch. + + Returns: + The archive file name. + """ + if deps_patch_sha: + revision = '%s_%s' % (revision, deps_patch_sha) + return 'build_product_%s.zip' % revision + + def FilePath(self, revision, deps_patch_sha=None): + return '%s/%s' % (self._ArchiveDirectory(), + self._ZipFileName(revision, deps_patch_sha)) + + def _ArchiveDirectory(self): + """Returns the directory name to download builds from.""" + return self._extra_src.GetArchiveDirectory() + + def BuildIsAvailable(bucket_name, remote_path): """Checks whether a build is currently archived at some place.""" logging.info('Checking existance: gs://%s/%s' % (bucket_name, remote_path))
diff --git a/tools/checkperms/checkperms.py b/tools/checkperms/checkperms.py index e2807c7..1e87e80 100755 --- a/tools/checkperms/checkperms.py +++ b/tools/checkperms/checkperms.py
@@ -147,10 +147,6 @@ 'chrome/test/data/extensions/uitest/plugins/plugin64.so', 'chrome/test/data/extensions/uitest/plugins_private/plugin32.so', 'chrome/test/data/extensions/uitest/plugins_private/plugin64.so', - 'components/test/data/component_updater/ihfokbkgjpifnbbojhneepfflplebdkc/' - 'ihfokbkgjpifnbbojhneepfflplebdkc_1/a_changing_binary_file', - 'components/test/data/component_updater/ihfokbkgjpifnbbojhneepfflplebdkc/' - 'ihfokbkgjpifnbbojhneepfflplebdkc_2/a_changing_binary_file', 'courgette/testdata/elf-32-1', 'courgette/testdata/elf-32-2', 'courgette/testdata/elf-64',
diff --git a/tools/chrome_proxy/integration_tests/chrome_proxy_benchmark.py b/tools/chrome_proxy/integration_tests/chrome_proxy_benchmark.py index 03ca98f14..318c9def 100644 --- a/tools/chrome_proxy/integration_tests/chrome_proxy_benchmark.py +++ b/tools/chrome_proxy/integration_tests/chrome_proxy_benchmark.py
@@ -7,139 +7,212 @@ from telemetry import benchmark -@benchmark.Enabled('android') class ChromeProxyLatency(benchmark.Benchmark): tag = 'latency' test = measurements.ChromeProxyLatency page_set = pagesets.Top20PageSet + @classmethod + def Name(cls): + return 'chrome_proxy_benchmark.latency.top_20' + def CustomizeBrowserOptions(self, options): options.AppendExtraBrowserArgs('--enable-spdy-proxy-auth') -@benchmark.Enabled('android') class ChromeProxyLatencyDirect(benchmark.Benchmark): tag = 'latency_direct' test = measurements.ChromeProxyLatency page_set = pagesets.Top20PageSet + @classmethod + def Name(cls): + return 'chrome_proxy_benchmark.latency_direct.top_20' -@benchmark.Enabled('android') + class ChromeProxyLatencySynthetic(ChromeProxyLatency): page_set = pagesets.SyntheticPageSet + @classmethod + def Name(cls): + return 'chrome_proxy_benchmark.latency.synthetic' -@benchmark.Enabled('android') + class ChromeProxyLatencySyntheticDirect(ChromeProxyLatencyDirect): page_set = pagesets.SyntheticPageSet + @classmethod + def Name(cls): + return 'chrome_proxy_benchmark.latency_direct.synthetic' -@benchmark.Enabled('android') + class ChromeProxyDataSaving(benchmark.Benchmark): tag = 'data_saving' test = measurements.ChromeProxyDataSaving page_set = pagesets.Top20PageSet + @classmethod + def Name(cls): + return 'chrome_proxy_benchmark.data_saving.top_20' + def CustomizeBrowserOptions(self, options): options.AppendExtraBrowserArgs('--enable-spdy-proxy-auth') -@benchmark.Enabled('android') class ChromeProxyDataSavingDirect(benchmark.Benchmark): tag = 'data_saving_direct' test = measurements.ChromeProxyDataSaving page_set = pagesets.Top20PageSet + @classmethod + def Name(cls): + return 'chrome_proxy_benchmark.data_saving_direct.top_20' -@benchmark.Enabled('android') + class ChromeProxyDataSavingSynthetic(ChromeProxyDataSaving): page_set = pagesets.SyntheticPageSet + @classmethod + def Name(cls): + return 'chrome_proxy_benchmark.data_saving.synthetic' -@benchmark.Enabled('android') + class ChromeProxyDataSavingSyntheticDirect(ChromeProxyDataSavingDirect): page_set = pagesets.SyntheticPageSet + @classmethod + def Name(cls): + return 'chrome_proxy_benchmark.data_saving_direct.synthetic' -@benchmark.Enabled('android') + class ChromeProxyHeaderValidation(benchmark.Benchmark): tag = 'header_validation' test = measurements.ChromeProxyHeaders page_set = pagesets.Top20PageSet + @classmethod + def Name(cls): + return 'chrome_proxy_benchmark.header_validation.top_20' -@benchmark.Enabled('android') + class ChromeProxyClientVersion(benchmark.Benchmark): tag = 'client_version' test = measurements.ChromeProxyClientVersion page_set = pagesets.SyntheticPageSet + @classmethod + def Name(cls): + return 'chrome_proxy_benchmark.client_version.synthetic' -@benchmark.Enabled('android') + class ChromeProxyClientType(benchmark.Benchmark): tag = 'client_type' test = measurements.ChromeProxyClientType page_set = pagesets.ClientTypePageSet + @classmethod + def Name(cls): + return 'chrome_proxy_benchmark.client_type.client_type' -@benchmark.Enabled('android') + class ChromeProxyBypass(benchmark.Benchmark): tag = 'bypass' test = measurements.ChromeProxyBypass page_set = pagesets.BypassPageSet + @classmethod + def Name(cls): + return 'chrome_proxy_benchmark.bypass.bypass' -@benchmark.Enabled('android') + class ChromeProxyCorsBypass(benchmark.Benchmark): tag = 'bypass' test = measurements.ChromeProxyCorsBypass page_set = pagesets.CorsBypassPageSet + @classmethod + def Name(cls): + return 'chrome_proxy_benchmark.bypass.corsbypass' -@benchmark.Enabled('android') + class ChromeProxyBlockOnce(benchmark.Benchmark): tag = 'block_once' test = measurements.ChromeProxyBlockOnce page_set = pagesets.BlockOncePageSet + @classmethod + def Name(cls): + return 'chrome_proxy_benchmark.block_once.block_once' + @benchmark.Enabled('android') -class ChromeProxySafeBrowsing(benchmark.Benchmark): - tag = 'safebrowsing' - test = measurements.ChromeProxySafebrowsing +# Safebrowsing is enabled for Android and iOS. +class ChromeProxySafeBrowsingOn(benchmark.Benchmark): + tag = 'safebrowsing_on' + test = measurements.ChromeProxySafebrowsingOn page_set = pagesets.SafebrowsingPageSet + @classmethod + def Name(cls): + return 'chrome_proxy_benchmark.safebrowsing_on.safebrowsing' -@benchmark.Enabled('android') + +# Safebrowsing is switched off for Android Webview and all desktop platforms. +class ChromeProxySafeBrowsingOff(benchmark.Benchmark): + tag = 'safebrowsing_off' + test = measurements.ChromeProxySafebrowsingOff + page_set = pagesets.SafebrowsingPageSet + + @classmethod + def Name(cls): + return 'chrome_proxy_benchmark.safebrowsing_off.safebrowsing' + class ChromeProxyHTTPFallbackProbeURL(benchmark.Benchmark): tag = 'fallback_probe' test = measurements.ChromeProxyHTTPFallbackProbeURL page_set = pagesets.SyntheticPageSet + @classmethod + def Name(cls): + return 'chrome_proxy_benchmark.fallback_probe.synthetic' -@benchmark.Enabled('android') + class ChromeProxyHTTPFallbackViaHeader(benchmark.Benchmark): tag = 'fallback_viaheader' test = measurements.ChromeProxyHTTPFallbackViaHeader page_set = pagesets.FallbackViaHeaderPageSet + @classmethod + def Name(cls): + return 'chrome_proxy_benchmark.fallback_viaheader.fallback_viaheader' -@benchmark.Enabled('android') + class ChromeProxyHTTPToDirectFallback(benchmark.Benchmark): tag = 'http_to_direct_fallback' test = measurements.ChromeProxyHTTPToDirectFallback page_set = pagesets.HTTPToDirectFallbackPageSet + @classmethod + def Name(cls): + return ('chrome_proxy_benchmark.http_to_direct_fallback.' + 'http_to_direct_fallback') -@benchmark.Enabled('android') + class ChromeProxyReenableAfterBypass(benchmark.Benchmark): tag = 'reenable_after_bypass' test = measurements.ChromeProxyReenableAfterBypass page_set = pagesets.ReenableAfterBypassPageSet + @classmethod + def Name(cls): + return 'chrome_proxy_benchmark.reenable_after_bypass.reenable_after_bypass' -@benchmark.Enabled('android') + class ChromeProxySmoke(benchmark.Benchmark): tag = 'smoke' test = measurements.ChromeProxySmoke page_set = pagesets.SmokePageSet + + @classmethod + def Name(cls): + return 'chrome_proxy_benchmark.smoke.smoke'
diff --git a/tools/chrome_proxy/integration_tests/chrome_proxy_measurements.py b/tools/chrome_proxy/integration_tests/chrome_proxy_measurements.py index eadc010..43d9397 100644 --- a/tools/chrome_proxy/integration_tests/chrome_proxy_measurements.py +++ b/tools/chrome_proxy/integration_tests/chrome_proxy_measurements.py
@@ -84,6 +84,9 @@ # The redirect from safebrowsing causes a timeout. Ignore that. try: super(ChromeProxyValidation, self).RunNavigateSteps(page, tab) + if self._expect_timeout: + raise metrics.ChromeProxyMetricException, ( + 'Timeout was expected, but did not occur') except exceptions.DevtoolsTargetCrashException, e: if self._expect_timeout: logging.warning('Navigation timeout on page %s', @@ -139,19 +142,27 @@ self._metrics.AddResultsForBlockOnce(tab, results) -class ChromeProxySafebrowsing(ChromeProxyValidation): +class ChromeProxySafebrowsingOn(ChromeProxyValidation): """Correctness measurement for safebrowsing.""" def __init__(self): - super(ChromeProxySafebrowsing, self).__init__() + super(ChromeProxySafebrowsingOn, self).__init__() def WillNavigateToPage(self, page, tab): - super(ChromeProxySafebrowsing, self).WillNavigateToPage(page, tab) + super(ChromeProxySafebrowsingOn, self).WillNavigateToPage(page, tab) self._expect_timeout = True def AddResults(self, tab, results): - self._metrics.AddResultsForSafebrowsing(tab, results) + self._metrics.AddResultsForSafebrowsingOn(tab, results) +class ChromeProxySafebrowsingOff(ChromeProxyValidation): + """Correctness measurement for safebrowsing.""" + + def __init__(self): + super(ChromeProxySafebrowsingOff, self).__init__() + + def AddResults(self, tab, results): + self._metrics.AddResultsForSafebrowsingOff(tab, results) _FAKE_PROXY_AUTH_VALUE = 'aabbccdd3b7579186c1b0620614fdb1f0000ffff' _TEST_SERVER = 'chromeproxy-test.appspot.com' @@ -325,12 +336,10 @@ """Smoke measurement for basic chrome proxy correctness.""" def __init__(self): - super(ChromeProxySmoke, self).__init__() + super(ChromeProxySmoke, self).__init__(restart_after_each_page=True) def WillNavigateToPage(self, page, tab): super(ChromeProxySmoke, self).WillNavigateToPage(page, tab) - if page.name == 'safebrowsing': - self._expect_timeout = True def AddResults(self, tab, results): # Map a page name to its AddResults func. @@ -349,7 +358,6 @@ self._metrics.AddResultsForDataSaving, ], 'bypass': [self._metrics.AddResultsForBypass], - 'safebrowsing': [self._metrics.AddResultsForSafebrowsing], } if not self._page.name in page_to_metrics: raise page_test.MeasurementFailure(
diff --git a/tools/chrome_proxy/integration_tests/chrome_proxy_metrics.py b/tools/chrome_proxy/integration_tests/chrome_proxy_metrics.py index 8857a56..63773da 100644 --- a/tools/chrome_proxy/integration_tests/chrome_proxy_metrics.py +++ b/tools/chrome_proxy/integration_tests/chrome_proxy_metrics.py
@@ -54,14 +54,6 @@ return (not self.ShouldHaveChromeProxyViaHeader() or self.HasChromeProxyViaHeader()) - def IsSafebrowsingResponse(self): - if (self.response.status == 307 and - self.response.GetHeader('X-Malware-Url') == '1' and - self.IsValidByViaHeader() and - self.response.GetHeader('Location') == self.response.url): - return True - return False - def GetChromeProxyClientType(self): """Get the client type directive from the Chrome-Proxy request header. @@ -270,27 +262,29 @@ results.AddValue(scalar.ScalarValue( results.current_page, 'bypass', 'count', bypass_count)) - def AddResultsForSafebrowsing(self, tab, results): - count = 0 - safebrowsing_count = 0 + def AddResultsForSafebrowsingOn(self, tab, results): + results.AddValue(scalar.ScalarValue( + results.current_page, 'safebrowsing', 'timeout responses', 1)) + def AddResultsForSafebrowsingOff(self, tab, results): + response_count = 0 for resp in self.IterResponses(tab): - count += 1 - if resp.IsSafebrowsingResponse(): - safebrowsing_count += 1 - else: + # Data reduction proxy should return the real response for sites with + # malware. + response_count += 1 + if not resp.HasChromeProxyViaHeader(): r = resp.response raise ChromeProxyMetricException, ( - '%s: Not a valid safe browsing response.\n' + '%s: Safebrowsing feature should be off for desktop and webview.\n' 'Reponse: status=(%d, %s)\nHeaders:\n %s' % ( r.url, r.status, r.status_text, r.headers)) - if count == safebrowsing_count: - results.AddValue(scalar.ScalarValue( - results.current_page, 'safebrowsing', 'boolean', True)) - else: + + if response_count == 0: raise ChromeProxyMetricException, ( - 'Safebrowsing failed (count=%d, safebrowsing_count=%d)\n' % ( - count, safebrowsing_count)) + 'Safebrowsing test failed: No valid responses received') + + results.AddValue(scalar.ScalarValue( + results.current_page, 'safebrowsing', 'responses', response_count)) def AddResultsForHTTPFallback(self, tab, results): via_fallback_count = 0
diff --git a/tools/chrome_proxy/integration_tests/chrome_proxy_pagesets/client_type.py b/tools/chrome_proxy/integration_tests/chrome_proxy_pagesets/client_type.py index 10dae718..83bc903 100644 --- a/tools/chrome_proxy/integration_tests/chrome_proxy_pagesets/client_type.py +++ b/tools/chrome_proxy/integration_tests/chrome_proxy_pagesets/client_type.py
@@ -54,3 +54,21 @@ url='http://check.googlezip.net/chrome-proxy-header/c=IOS', page_set=self, bypass_for_client_type='ios')) + + # Page that should cause a bypass for Linux clients. + self.AddUserStory(ClientTypePage( + url='http://check.googlezip.net/chrome-proxy-header/c=LINUX', + page_set=self, + bypass_for_client_type='linux')) + + # Page that should cause a bypass for Windows clients. + self.AddUserStory(ClientTypePage( + url='http://check.googlezip.net/chrome-proxy-header/c=WIN', + page_set=self, + bypass_for_client_type='win')) + + # Page that should cause a bypass for ChromeOS clients. + self.AddUserStory(ClientTypePage( + url='http://check.googlezip.net/chrome-proxy-header/c=CHROMEOS', + page_set=self, + bypass_for_client_type='chromeos'))
diff --git a/tools/chrome_proxy/integration_tests/chrome_proxy_pagesets/smoke.py b/tools/chrome_proxy/integration_tests/chrome_proxy_pagesets/smoke.py index 6b11d44..49de585 100644 --- a/tools/chrome_proxy/integration_tests/chrome_proxy_pagesets/smoke.py +++ b/tools/chrome_proxy/integration_tests/chrome_proxy_pagesets/smoke.py
@@ -50,7 +50,6 @@ url='http://aws1.mdw.la/bypass/', page_set=page_set, name='bypass') - self.restart_after = True class Page4(SmokePage): @@ -79,22 +78,6 @@ name='compression: css') -class Page6(SmokePage): - - """ - Why: Expect 'malware ahead' page. Use a short navigation timeout because no - response will be received. - """ - - def __init__(self, page_set): - super(Page6, self).__init__( - url='http://www.ianfette.org/', - page_set=page_set, - name='safebrowsing') - - def RunNavigateSteps(self, action_runner): - action_runner.NavigateToPage(self, timeout_in_seconds=5) - class SmokePageSet(page_set_module.PageSet): @@ -109,4 +92,3 @@ self.AddUserStory(Page3(self)) self.AddUserStory(Page4(self)) self.AddUserStory(Page5(self)) - self.AddUserStory(Page6(self))
diff --git a/tools/clang/scripts/update.py b/tools/clang/scripts/update.py index 84c39cbb..7c67aedd 100755 --- a/tools/clang/scripts/update.py +++ b/tools/clang/scripts/update.py
@@ -217,7 +217,8 @@ '-DLLVM_ENABLE_ASSERTIONS=ON', LLVM_DIR]) RunCommand(GetVSVersion().SetupScript('x86') + ['&&', 'ninja', 'compiler-rt']) - # TODO(hans): Make this (and the .gypi file) version number independent. + # TODO(hans): Make this (and the .gypi and .isolate file) version number + # independent. asan_rt_lib_src_dir = os.path.join(COMPILER_RT_BUILD_DIR, 'lib', 'clang', VERSION, 'lib', 'windows') asan_rt_lib_dst_dir = os.path.join(LLVM_BUILD_DIR, 'lib', 'clang',
diff --git a/tools/cygprofile/patch_orderfile.py b/tools/cygprofile/patch_orderfile.py index 6c8bc43..9f50b21 100755 --- a/tools/cygprofile/patch_orderfile.py +++ b/tools/cygprofile/patch_orderfile.py
@@ -155,26 +155,53 @@ with open(filename, 'r') as f: return _GetSymbolsFromStream(f.xreadlines()) +def _SymbolsWithSameOffset(profiled_symbol, name_to_symbol_info, + offset_to_symbol_info): + """Expand a profiled symbol to include all symbols which share an offset + with that symbol. + Args: + profiled_symbol: the string symbol name to be expanded. + name_to_symbol_info: {name: [symbol_info1], ...}, as returned by + GetSymbolInfosFromBinary + offset_to_symbol_info: {offset: [symbol_info1, ...], ...} -def _MatchProfiledSymbols(profiled_symbols, name_to_symbol_infos): - """Filter name_to_symbol_infos with the keys from profiled_symbols. + Returns: + A list of symbol names, or an empty list if profiled_symbol was not in + name_to_symbol_info. + """ + if not profiled_symbol in name_to_symbol_info: + return [] + symbol_infos = name_to_symbol_info[profiled_symbol] + expanded = [] + for symbol_info in symbol_infos: + expanded += (s.name for s in offset_to_symbol_info[symbol_info.offset]) + return expanded + +def _ExpandSymbols(profiled_symbols, name_to_symbol_infos, + offset_to_symbol_infos): + """Expand all of the symbols in profiled_symbols to include any symbols which + share the same address. Args: profiled_symbols: Symbols to match - name_to_symbol_infos: {name: [symbol_infos], ...}, as returned by + name_to_symbol_infos: {name: [symbol_info1], ...}, as returned by GetSymbolInfosFromBinary + offset_to_symbol_infos: {offset: [symbol_info1, ...], ...} Returns: - A list of the symbol infos that have been matched. + A list of the symbol names. """ found_symbols = 0 missing_symbols = [] - symbol_infos = [] + all_symbols = [] for name in profiled_symbols: - if name in name_to_symbol_infos: - symbol_infos += name_to_symbol_infos[name] + expansion = _SymbolsWithSameOffset(name, + name_to_symbol_infos, offset_to_symbol_infos) + if expansion: found_symbols += 1 + all_symbols += expansion else: + all_symbols.append(name) missing_symbols.append(name) logging.info('symbols found: %d\n' % found_symbols) if missing_symbols > 0: @@ -183,27 +210,7 @@ logging.warning('First %d missing symbols:\n%s' % ( missing_symbols_to_show, '\n'.join(missing_symbols[:missing_symbols_to_show]))) - return symbol_infos - - -def _ExpandSymbolsWithDupsFromSameOffset(symbol_infos, offset_to_symbol_infos): - """Return the SymbolInfo sharing the same offset as those from symbol_infos. - - Args: - symbol_infos: list of symbols to look for - offset_to_symbol_infos: {offset: [symbol_info1, ...], ...} - - Returns: - A list of matching symbol names - """ - seen_offsets = set() - matching_symbols = [] - for symbol in symbol_infos: - if symbol.offset not in seen_offsets: - seen_offsets.add(symbol.offset) - matching_symbols += [ - s.name for s in offset_to_symbol_infos[symbol.offset]] - return matching_symbols + return all_symbols def _PrintSymbolsWithPrefixes(symbol_names, output_file): @@ -226,11 +233,9 @@ (offset_to_symbol_infos, name_to_symbol_infos) = _GetSymbolInfosFromBinary( binary_filename) profiled_symbols = _GetSymbolsFromOrderfile(orderfile_filename) - matched_symbols = _MatchProfiledSymbols( - profiled_symbols, name_to_symbol_infos) - symbols_by_offset = _ExpandSymbolsWithDupsFromSameOffset( - matched_symbols, offset_to_symbol_infos) - _PrintSymbolsWithPrefixes(symbols_by_offset, sys.stdout) + expanded_symbols = _ExpandSymbols( + profiled_symbols, name_to_symbol_infos, offset_to_symbol_infos) + _PrintSymbolsWithPrefixes(expanded_symbols, sys.stdout) # The following is needed otherwise Gold only applies a partial sort. print '.text' # gets methods not in a section, such as assembly print '.text.*' # gets everything else
diff --git a/tools/cygprofile/patch_orderfile_unittest.py b/tools/cygprofile/patch_orderfile_unittest.py index 7066e2e..207ff57c 100755 --- a/tools/cygprofile/patch_orderfile_unittest.py +++ b/tools/cygprofile/patch_orderfile_unittest.py
@@ -78,28 +78,21 @@ names[1], "_ZN2v88internal33HEnvironmentLivenessAnalysisPhase3RunEv") - def testMatchProfiledSymbols(self): + def testExpandSymbols(self): symbol_name = "dummySymbol" + symbol_name2 = "other" profiled_symbol_names = [symbol_name, "symbolThatShouldntMatch"] name_to_symbol_infos = {symbol_name: [ patch_orderfile.SymbolInfo(0x42, 0x12, symbol_name)]} - matched_symbols = patch_orderfile._MatchProfiledSymbols( - profiled_symbol_names, name_to_symbol_infos) - self.assertEquals(len(matched_symbols), 1) - self.assertEquals(matched_symbols[0], name_to_symbol_infos[symbol_name][0]) - - def testExpandSymbolsWithDupsFromSameOffset(self): - symbol_name = "dummySymbol" - symbol_name2 = "other" - symbols = [patch_orderfile.SymbolInfo(0x42, 0x12, symbol_name)] offset_to_symbol_infos = { 0x42: [patch_orderfile.SymbolInfo(0x42, 0x12, symbol_name), patch_orderfile.SymbolInfo(0x42, 0x12, symbol_name2)]} - symbol_names = patch_orderfile._ExpandSymbolsWithDupsFromSameOffset( - symbols, offset_to_symbol_infos) - self.assertEquals(len(symbol_names), 2) + symbol_names = patch_orderfile._ExpandSymbols( + profiled_symbol_names, name_to_symbol_infos, offset_to_symbol_infos) + self.assertEquals(len(symbol_names), 3) self.assertEquals(symbol_names[0], symbol_name) self.assertEquals(symbol_names[1], symbol_name2) + self.assertEquals(symbol_names[2], "symbolThatShouldntMatch") def testPrintSymbolWithPrefixes(self): class FakeOutputFile(object):
diff --git a/tools/gn/trace.cc b/tools/gn/trace.cc index 036ac53..c8107931 100644 --- a/tools/gn/trace.cc +++ b/tools/gn/trace.cc
@@ -123,7 +123,7 @@ : item_(nullptr), done_(false) { if (trace_log) { item_ = new TraceItem(t, name, base::PlatformThread::CurrentId()); - item_->set_begin(base::TimeTicks::HighResNow()); + item_->set_begin(base::TimeTicks::Now()); } } @@ -132,7 +132,7 @@ if (trace_log) { item_ = new TraceItem(t, label.GetUserVisibleName(false), base::PlatformThread::CurrentId()); - item_->set_begin(base::TimeTicks::HighResNow()); + item_->set_begin(base::TimeTicks::Now()); } } @@ -154,7 +154,7 @@ if (!done_) { done_ = true; if (trace_log) { - item_->set_end(base::TimeTicks::HighResNow()); + item_->set_end(base::TimeTicks::Now()); AddTrace(item_); } }
diff --git a/tools/ipc_fuzzer/mutate/generate.cc b/tools/ipc_fuzzer/mutate/generate.cc index c7e9e88..0a17fdd 100644 --- a/tools/ipc_fuzzer/mutate/generate.cc +++ b/tools/ipc_fuzzer/mutate/generate.cc
@@ -410,7 +410,7 @@ struct GenerateTraits<std::map<A, B> > { static bool Generate(std::map<A, B>* p, Generator* generator) { static int g_depth = 0; - size_t count = ++g_depth > 3 ? 0 : RandInRange(20); + size_t count = ++g_depth > 3 ? 0 : RandInRange(10); std::pair<A, B> place_holder; for (size_t i = 0; i < count; ++i) { if (!GenerateParam(&place_holder, generator)) { @@ -661,37 +661,6 @@ }; template <> -struct GenerateTraits<GURL> { - static bool Generate(GURL *p, Generator* generator) { - const char url_chars[] = "Ahtp0:/.?+\\%&#"; - size_t count = RandInRange(100); - std::string random_url; - for (size_t i = 0; i < count; ++i) - random_url += url_chars[RandInRange(sizeof(url_chars) - 1)]; - int selector = RandInRange(10); - if (selector == 0) - random_url = std::string("http://") + random_url; - else if (selector == 1) - random_url = std::string("file://") + random_url; - else if (selector == 2) - random_url = std::string("javascript:") + random_url; - else if (selector == 2) - random_url = std::string("data:") + random_url; - *p = GURL(random_url); - return true; - } -}; - -// FIXME: Actually generate something. -template <> -struct GenerateTraits<SkBitmap> { - static bool Generate(SkBitmap* p, Generator* generator) { - *p = SkBitmap(); - return true; - } -}; - -template <> struct GenerateTraits<cc::CompositorFrame> { // FIXME: this should actually generate something static bool Generate(cc::CompositorFrame* p, Generator* generator) { @@ -827,6 +796,28 @@ }; template <> +struct GenerateTraits<dns_prefetch::LookupRequest> { + static bool Generate(dns_prefetch::LookupRequest* p, Generator* generator) { + dns_prefetch::LookupRequest request; + if (!GenerateParam(&request.hostname_list, generator)) + return false; + *p = request; + return true; + } +}; + +template <> +struct GenerateTraits<extensions::URLPatternSet> { + static bool Generate(extensions::URLPatternSet* p, Generator* generator) { + std::set<URLPattern> patterns; + if (!GenerateParam(&patterns, generator)) + return false; + *p = extensions::URLPatternSet(patterns); + return true; + } +}; + +template <> struct GenerateTraits<gpu::Mailbox> { static bool Generate(gpu::Mailbox *p, Generator* generator) { generator->GenerateBytes(p->name, sizeof(p->name)); @@ -835,6 +826,60 @@ }; template <> +struct GenerateTraits<gpu::MailboxHolder> { + static bool Generate(gpu::MailboxHolder *p, Generator* generator) { + gpu::Mailbox mailbox; + uint32_t texture_target; + uint32_t sync_point; + if (!GenerateParam(&mailbox, generator)) + return false; + if (!GenerateParam(&texture_target, generator)) + return false; + if (!GenerateParam(&sync_point, generator)) + return false; + *p = gpu::MailboxHolder(mailbox, texture_target, sync_point); + return true; + } +}; + +template <> +struct GenerateTraits<gpu::ValueState> { + static bool Generate(gpu::ValueState* p, Generator* generator) { + gpu::ValueState state; + for (int i = 0; i < 4; i++) { + if (!GenerateParam(&state.float_value[i], generator)) + return false; + if (!GenerateParam(&state.int_value[i], generator)) + return false; + } + *p = state; + return true; + } +}; + +template <> +struct GenerateTraits<GURL> { + static bool Generate(GURL *p, Generator* generator) { + const char url_chars[] = "Ahtp0:/.?+\\%&#"; + size_t count = RandInRange(100); + std::string random_url; + for (size_t i = 0; i < count; ++i) + random_url += url_chars[RandInRange(sizeof(url_chars) - 1)]; + int selector = RandInRange(10); + if (selector == 0) + random_url = std::string("http://") + random_url; + else if (selector == 1) + random_url = std::string("file://") + random_url; + else if (selector == 2) + random_url = std::string("javascript:") + random_url; + else if (selector == 2) + random_url = std::string("data:") + random_url; + *p = GURL(random_url); + return true; + } +}; + +template <> struct GenerateTraits<media::AudioParameters> { static bool Generate(media::AudioParameters *p, Generator* generator) { int format; @@ -1143,6 +1188,88 @@ } }; +template <> +struct GenerateTraits<remoting::ScreenResolution> { + static bool Generate(remoting::ScreenResolution* p, Generator* generator) { + webrtc::DesktopSize size; + webrtc::DesktopVector vector; + if (!GenerateParam(&size, generator)) + return false; + if (!GenerateParam(&vector, generator)) + return false; + *p = remoting::ScreenResolution(size, vector); + return true; + } +}; + +// FIXME: Actually generate something. +template <> +struct GenerateTraits<SkBitmap> { + static bool Generate(SkBitmap* p, Generator* generator) { + *p = SkBitmap(); + return true; + } +}; + +template <> +struct GenerateTraits<url::Origin> { + static bool Generate(url::Origin* p, Generator* generator) { + std::string origin; + if (!GenerateParam(&origin, generator)) + return false; + *p = url::Origin(origin); + return true; + } +}; + +template <> +struct GenerateTraits<webrtc::DesktopSize> { + static bool Generate(webrtc::DesktopSize* p, Generator* generator) { + int32_t width; + int32_t height; + if (!GenerateParam(&width, generator)) + return false; + if (!GenerateParam(&height, generator)) + return false; + *p = webrtc::DesktopSize(width, height); + return true; + } +}; + +template <> +struct GenerateTraits<webrtc::DesktopVector> { + static bool Generate(webrtc::DesktopVector* p, Generator* generator) { + int32_t x; + int32_t y; + if (!GenerateParam(&x, generator)) + return false; + if (!GenerateParam(&y, generator)) + return false; + p->set(x, y); + return true; + } +}; + +template <> +struct GenerateTraits<webrtc::DesktopRect> { + static bool Generate(webrtc::DesktopRect* p, Generator* generator) { + int32_t left; + int32_t top; + int32_t right; + int32_t bottom; + if (!GenerateParam(&left, generator)) + return false; + if (!GenerateParam(&top, generator)) + return false; + if (!GenerateParam(&right, generator)) + return false; + if (!GenerateParam(&bottom, generator)) + return false; + *p = webrtc::DesktopRect::MakeLTRB(left, top, right, bottom); + return true; + } +}; + // Redefine macros to generate generating from traits declarations. // STRUCT declarations cause corresponding STRUCT_TRAITS declarations to occur. #undef IPC_STRUCT_BEGIN
diff --git a/tools/memory_inspector/chrome_app/build.sh b/tools/memory_inspector/chrome_app/build.sh index 7d3e9dd..e622dcd5 100755 --- a/tools/memory_inspector/chrome_app/build.sh +++ b/tools/memory_inspector/chrome_app/build.sh
@@ -47,7 +47,7 @@ # Download Memory Inspector prebuilt files. download_from_google_storage --directory "${MEMORY_INSPECTOR_PREBUILTS_DIR}" \ - --bucket "${MEMORY_INSPECTOR_PREBUILTS_BUCKET}" + --bucket "${MEMORY_INSPECTOR_PREBUILTS_BUCKET}" --no_auth # Add Memory Inspector dependencies to pydata_pnacl.tar. tmp_dir="$(mktemp -d)"
diff --git a/tools/memory_inspector/chrome_app/template/inject.js b/tools/memory_inspector/chrome_app/template/inject.js new file mode 100644 index 0000000..6138d93 --- /dev/null +++ b/tools/memory_inspector/chrome_app/template/inject.js
@@ -0,0 +1,13 @@ +// Copyright 2015 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. + +'use strict'; + +/** + * Script injected into the Memory Inspector webpage which disables native + * tracing. + */ +var script = document.createElement('script'); +script.textContent = 'window.DISABLE_NATIVE_TRACING = true;'; +document.head.appendChild(script);
diff --git a/tools/memory_inspector/chrome_app/template/main_window.js b/tools/memory_inspector/chrome_app/template/main_window.js index fc9e124d1..c76da7a 100644 --- a/tools/memory_inspector/chrome_app/template/main_window.js +++ b/tools/memory_inspector/chrome_app/template/main_window.js
@@ -368,6 +368,8 @@ console.log('Inspector server ready. Loading the inspector view...'); this.inspectorViewElement_.addEventListener('loadstop', this.onInspectorLoaded_.bind(this)); + this.inspectorViewElement_.addEventListener('loadcommit', + this.onInspectorNavigated_.bind(this)); this.inspectorViewElement_.src = 'http://127.0.0.1:' + MemoryInspectorConfig.PORT; }; @@ -382,6 +384,17 @@ document.body.classList.add('inspector_view_visible'); }; +/** + * Listener called when the inspector view navigates to the inspector website. + * @private + */ +MemoryInspectorWindow.prototype.onInspectorNavigated_ = function() { + this.inspectorViewElement_.executeScript({ + 'file': 'inject.js', + 'runAt': 'document_start' + }); +}; + window.addEventListener('load', function() { // Create the singleton MemoryInspectorWindow instance and initialize it. var mainWindow = new MemoryInspectorWindow();
diff --git a/tools/memory_inspector/chrome_app/template/manifest.json b/tools/memory_inspector/chrome_app/template/manifest.json index a88b39f..b797fc0 100644 --- a/tools/memory_inspector/chrome_app/template/manifest.json +++ b/tools/memory_inspector/chrome_app/template/manifest.json
@@ -1,7 +1,7 @@ { "name": "Memory Inspector", "description": "Memory inspector tool for Android", - "version": "0.1.0", + "version": "0.1.2", "manifest_version": 2, "icons": { "16": "images/icon_16.png", @@ -30,6 +30,6 @@ "udp-send-to:*:*" ] }, - "http://127.0.0.1:*/*" + "http://127.0.0.1/*" ] }
diff --git a/tools/memory_inspector/classification_rules/default/mmap-android.py b/tools/memory_inspector/classification_rules/default/mmap-android.py index 1a8d0d0..336edfd 100644 --- a/tools/memory_inspector/classification_rules/default/mmap-android.py +++ b/tools/memory_inspector/classification_rules/default/mmap-android.py
@@ -76,7 +76,7 @@ 'children': [ { 'name': 'GPU', - 'mmap_file': r'(nv)|(mali)', + 'mmap_file': r'(nv)|(mali)|(kgsl)', }, ], },
diff --git a/tools/memory_inspector/memory_inspector/backends/adb_client.py b/tools/memory_inspector/memory_inspector/backends/adb_client.py index 9d391f3d..3f86105 100644 --- a/tools/memory_inspector/memory_inspector/backends/adb_client.py +++ b/tools/memory_inspector/memory_inspector/backends/adb_client.py
@@ -20,6 +20,7 @@ ADB_PORT = 5037 TIMEOUT = 5 +ADB_NOT_RUNNING_MESSAGE = 'ADB daemon not running. Run \'adb start-server\'.' class ADBClientError(Exception): @@ -52,12 +53,14 @@ self._sock = socket.create_connection(('127.0.0.1', ADB_PORT), timeout=TIMEOUT) except socket.error: - raise ADBClientError('adb daemon not running. Run adb start-server.') + raise ADBClientError(ADB_NOT_RUNNING_MESSAGE) if self._transport: self.SendCmd('host:transport:' + self._transport) return self - def __exit__(self, _type, _value, _traceback): + def __exit__(self, exc_type, exc_value, exc_traceback): + if exc_type is socket.error: + raise ADBClientError(ADB_NOT_RUNNING_MESSAGE) try: self._sock.close() except Exception as e:
diff --git a/tools/memory_inspector/memory_inspector/frontends/www_content/index.html b/tools/memory_inspector/memory_inspector/frontends/www_content/index.html index c3c053d..79388f2 100644 --- a/tools/memory_inspector/memory_inspector/frontends/www_content/index.html +++ b/tools/memory_inspector/memory_inspector/frontends/www_content/index.html
@@ -87,7 +87,7 @@ </div> <div> <label for="ps-tracer-period">Period [s.]</label> - <input type="text" id="ps-tracer-period" value="20"> + <input type="text" id="ps-tracer-period" value="10"> </div> <div> <label for="ps-tracer-snapshots">Num snapshots</label> @@ -234,4 +234,4 @@ </div> </body> -</html> \ No newline at end of file +</html>
diff --git a/tools/memory_inspector/memory_inspector/frontends/www_content/js/devices.js b/tools/memory_inspector/memory_inspector/frontends/www_content/js/devices.js index f96a447..9cf6b6a 100644 --- a/tools/memory_inspector/memory_inspector/frontends/www_content/js/devices.js +++ b/tools/memory_inspector/memory_inspector/frontends/www_content/js/devices.js
@@ -65,8 +65,8 @@ if (data.length > 0) { this.onDeviceSelectionChange_(); // Start monitoring the first device. } else { - rootUi.showDialog('No devices could be detected. Check the settings tab ' + - 'to ensure that the adb path is properly configured.'); + rootUi.showDialog('No devices detected. Make sure that adb is running on ' + + 'the host and check \'adb devices\'.'); } };
diff --git a/tools/memory_inspector/memory_inspector/frontends/www_content/js/processes.js b/tools/memory_inspector/memory_inspector/frontends/www_content/js/processes.js index a7dc1421..75e60218 100644 --- a/tools/memory_inspector/memory_inspector/frontends/www_content/js/processes.js +++ b/tools/memory_inspector/memory_inspector/frontends/www_content/js/processes.js
@@ -39,7 +39,7 @@ // Set-up the tracer dialog. $('#ps-tracer-dialog').dialog({autoOpen: false, modal: true, width: 400, buttons: {'Start': this.startTracingSelectedProcess_.bind(this)}}); - $('#ps-tracer-period').spinner({min: 0, step: 20}); + $('#ps-tracer-period').spinner({min: 0, step: 10}); $('#ps-tracer-snapshots').spinner({min: 1, max: 100}); // Create the process table. @@ -65,14 +65,14 @@ this.snapshotSelectedProcess_ = function() { if (!this.selProcUri_) - return alert('Must select a process!'); + return rootUi.showDialog('Must select a process!'); mmap.dumpMmaps(this.selProcUri_, true); rootUi.showTab('prof'); }; this.dumpSelectedProcessMmaps_ = function() { if (!this.selProcUri_) - return alert('Must select a process!'); + return rootUi.showDialog('Must select a process!'); mmap.dumpMmaps(this.selProcUri_, false); rootUi.showTab('mm'); }; @@ -99,14 +99,18 @@ this.showTracingDialog_ = function() { if (!this.selProcUri_) - return alert('Must select a process!'); + return rootUi.showDialog('Must select a process!'); $('#ps-tracer-process').val(this.selProcName_); + if (window.DISABLE_NATIVE_TRACING) { + $('#ps-tracer-bt').hide(); + $('label[for="ps-tracer-bt"]').hide(); + } $('#ps-tracer-dialog').dialog('open'); }; this.startTracingSelectedProcess_ = function() { if (!this.selProcUri_) - return alert('The process ' + this.selProcUri_ + ' died.'); + return rootUi.showDialog('The process ' + this.selProcUri_ + ' died.'); var traceNativeHeap = $('#ps-tracer-bt').prop('checked'); $('#ps-tracer-dialog').dialog('close'); @@ -313,4 +317,4 @@ $(document).ready(this.onDomReady_.bind(this)); -})(); \ No newline at end of file +})();
diff --git a/tools/memory_inspector/memory_inspector/frontends/www_content/js/rootUi.js b/tools/memory_inspector/memory_inspector/frontends/www_content/js/rootUi.js index 1954c7e..bb4c80e 100644 --- a/tools/memory_inspector/memory_inspector/frontends/www_content/js/rootUi.js +++ b/tools/memory_inspector/memory_inspector/frontends/www_content/js/rootUi.js
@@ -11,6 +11,11 @@ webservice.onServerUnreachableOrTimeout = this.onServerUnreachableOrTimeout.bind(this); + if (window.DISABLE_NATIVE_TRACING) { + $('#tabs').tabs('disable', '#tabs-nheap'); + $('#tabs').tabs('disable', '#tabs-settings'); + } + // Initialize the status bar. $('#status_messages').mouseenter(function() { $('#status_bar').addClass('expanded'); @@ -81,4 +86,4 @@ $(document).ready(this.onDomReady_.bind(this)); -})(); \ No newline at end of file +})();
diff --git a/tools/memory_inspector/memory_inspector/frontends/www_content/js/storage.js b/tools/memory_inspector/memory_inspector/frontends/www_content/js/storage.js index eddd9aa..62563ee0 100644 --- a/tools/memory_inspector/memory_inspector/frontends/www_content/js/storage.js +++ b/tools/memory_inspector/memory_inspector/frontends/www_content/js/storage.js
@@ -25,6 +25,9 @@ .click(this.dumpMmapForSelectedSnapshot_.bind(this)); $('#storage-dump-nheap').button({icons:{primary: 'ui-icon-calculator'}}) .click(this.dumpNheapForSelectedSnapshot_.bind(this)); + if (window.DISABLE_NATIVE_TRACING) { + $('#storage-dump-nheap').hide(); + } // Create the table. this.table_ = new google.visualization.Table($('#storage-table')[0]); @@ -36,6 +39,10 @@ } this.onListAjaxResponse_ = function(data) { + if (window.DISABLE_NATIVE_TRACING) { + // Do not show the native heap column if native tracing is disabled. + data.cols.pop(); + } this.tableData_ = new google.visualization.DataTable(data); this.redraw(); }; @@ -44,7 +51,7 @@ // Generates a mmap profile for the selected snapshots. var sel = this.table_.getSelection(); if (!sel.length || !this.tableData_) { - alert('No snapshots selected!'); + rootUi.showDialog('No snapshots selected!'); return; } var archiveName = null; @@ -54,7 +61,8 @@ var row = sel[i].row; var curArchive = this.tableData_.getValue(row, 0); if (archiveName && curArchive != archiveName) { - alert('All the selected snapshots must belong to the same archive!'); + rootUi.showDialog( + 'All the selected snapshots must belong to the same archive!'); return; } archiveName = curArchive; @@ -67,7 +75,7 @@ this.dumpMmapForSelectedSnapshot_ = function() { var sel = this.table_.getSelection(); if (sel.length != 1) { - alert('Please select only one snapshot.') + rootUi.showDialog('Please select only one snapshot.') return; } @@ -80,7 +88,7 @@ this.dumpNheapForSelectedSnapshot_ = function() { var sel = this.table_.getSelection(); if (sel.length != 1) { - alert('Please select only one snapshot.') + rootUi.showDialog('Please select only one snapshot.') return; } @@ -96,7 +104,7 @@ // Generates a native heap profile for the selected snapshots. var sel = this.table_.getSelection(); if (!sel.length || !this.tableData_) { - alert('No snapshots selected!'); + rootUi.showDialog('No snapshots selected!'); return; } var archiveName = null; @@ -106,7 +114,8 @@ var row = sel[i].row; var curArchive = this.tableData_.getValue(row, 0); if (archiveName && curArchive != archiveName) { - alert('All the selected snapshots must belong to the same archive!'); + rootUi.showDialog( + 'All the selected snapshots must belong to the same archive!'); return; } if (!this.checkHasNativeHapDump_(row)) @@ -120,7 +129,7 @@ this.checkHasNativeHapDump_ = function(row) { if (!this.tableData_.getValue(row, 3)) { - alert('The selected snapshot doesn\'t have a heap dump!'); + rootUi.showDialog('The selected snapshot doesn\'t have a heap dump!'); return false; } return true; @@ -137,13 +146,15 @@ this.profileMmapForSelectedSnapshots.bind(this, rule))); }, this); - this.profileMenu_.append( - $('<li/>').addClass('header').text('Native heap rules')); - profiler.rulesets['nheap'].forEach(function(rule) { + if (!window.DISABLE_NATIVE_TRACING) { this.profileMenu_.append( - $('<li/>').text(rule).click( - this.profileNativeForSelectedSnapshots.bind(this, rule))); - }, this); + $('<li/>').addClass('header').text('Native heap rules')); + profiler.rulesets['nheap'].forEach(function(rule) { + this.profileMenu_.append( + $('<li/>').text(rule).click( + this.profileNativeForSelectedSnapshots.bind(this, rule))); + }, this); + } this.profileMenu_.menu(); }; @@ -168,4 +179,4 @@ $(document).ready(this.onDomReady_.bind(this)); -})(); \ No newline at end of file +})();
diff --git a/tools/memory_inspector/memory_inspector/frontends/www_content/js/webservice.js b/tools/memory_inspector/memory_inspector/frontends/www_content/js/webservice.js index 2967d66..5f4b8f2 100644 --- a/tools/memory_inspector/memory_inspector/frontends/www_content/js/webservice.js +++ b/tools/memory_inspector/memory_inspector/frontends/www_content/js/webservice.js
@@ -23,6 +23,8 @@ console.log('AJAX error (req: ' + path + ').'); console.log('HTTP response: ' + xhr.status + ' ' + thrownError); console.log(xhr.responseText); + rootUi.showDialog((xhr.responseText || 'Unknown server error.') + + ' Check the console for more details.'); if (errorCallback) errorCallback(xhr.status, xhr.responseText); if (xhr.readyState < 4 && this_.onServerUnreachableOrTimeout != null) @@ -31,4 +33,4 @@ }); }; -})(); \ No newline at end of file +})();
diff --git a/tools/memory_inspector/memory_inspector/frontends/www_server.py b/tools/memory_inspector/memory_inspector/frontends/www_server.py index 9e7e604..d75c973 100644 --- a/tools/memory_inspector/memory_inspector/frontends/www_server.py +++ b/tools/memory_inspector/memory_inspector/frontends/www_server.py
@@ -28,6 +28,7 @@ import os import posixpath import re +import traceback import urlparse import uuid import wsgiref.simple_server @@ -42,9 +43,10 @@ from memory_inspector.frontends import background_tasks -_HTTP_OK = '200 - OK' -_HTTP_GONE = '410 - Gone' -_HTTP_NOT_FOUND = '404 - Not Found' +_HTTP_OK = '200 OK' +_HTTP_GONE = '410 Gone' +_HTTP_NOT_FOUND = '404 Not Found' +_HTTP_INTERNAL_ERROR = '500 Internal Server Error' _PERSISTENT_STORAGE_PATH = os.path.join( os.path.expanduser('~'), '.config', 'memory_inspector') _CONTENT_DIR = os.path.abspath(os.path.join( @@ -86,22 +88,28 @@ @staticmethod def Handle(method, path, req_vars): """Finds a matching handler and calls it (or returns a 404 - Not Found).""" + cache_headers = [('Cache-Control', 'no-cache'), + ('Expires', 'Fri, 19 Sep 1986 05:00:00 GMT')] for (match_method, path_regex, output_filter, fn) in UriHandler._handlers: if method != match_method: continue m = re.match(path_regex, path) if not m: continue - (http_code, headers, body) = fn(m.groups(), req_vars) - return output_filter(http_code, headers, body) + try: + (http_code, headers, body) = fn(m.groups(), req_vars) + except Exception as e: + traceback.print_exc() + return _HTTP_INTERNAL_ERROR, [], str(e) + return output_filter(http_code, cache_headers + headers, body) return (_HTTP_NOT_FOUND, [], 'No AJAX handlers found') class AjaxHandler(UriHandler): """Decorator for routing AJAX requests. - This decorator essentially groups the JSON serialization and the cache headers - which is shared by most of the handlers defined below. + This decorator performs JSON serialization which is shared by most of the + handlers defined below. """ def __init__(self, path_regex, verb='GET'): super(AjaxHandler, self).__init__( @@ -110,9 +118,7 @@ @staticmethod def AjaxOutputFilter(http_code, headers, body): serialized_content = json.dumps(body, cls=serialization.Encoder) - extra_headers = [('Cache-Control', 'no-cache'), - ('Expires', 'Fri, 19 Sep 1986 05:00:00 GMT')] - return http_code, headers + extra_headers, serialized_content + return http_code, headers, serialized_content @AjaxHandler('/ajax/backends') @@ -637,8 +643,6 @@ @UriHandler(r'^(?!/ajax)/(.*)$') def _StaticContent(args, req_vars): # pylint: disable=W0613 - # Give the browser a 1-day TTL cache to minimize the start-up time. - cache_headers = [('Cache-Control', 'max-age=86400, public')] req_path = args[0] if args[0] else 'index.html' file_path = os.path.abspath(os.path.join(_CONTENT_DIR, req_path)) if (os.path.isfile(file_path) and @@ -649,8 +653,8 @@ mtype = guessed_mime[0] with open(file_path, 'rb') as f: body = f.read() - return _HTTP_OK, cache_headers + [('Content-Type', mtype)], body - return _HTTP_NOT_FOUND, cache_headers, file_path + ' not found' + return _HTTP_OK, [('Content-Type', mtype)], body + return _HTTP_NOT_FOUND, [], file_path + ' not found' def _GetDevice(args):
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml index b438d74f4..efde306 100644 --- a/tools/metrics/actions/actions.xml +++ b/tools/metrics/actions/actions.xml
@@ -189,6 +189,15 @@ <description>Please enter the description of this user action.</description> </action> +<action name="AboutFlags_mark-non-secure-as"> + <owner>palmer@chromium.org</owner> + <owner>felt@chromium.org</owner> + <description> + This flag lets users opt into or out of marking HTTP as Dubious or as + Non-Secure. The action is emitted once per startup when the flag is active. + </description> +</action> + <action name="AboutFlags_match-preview"> <owner>Please list the metric's owners. Add more owner tags as needed.</owner> <description>Please enter the description of this user action.</description> @@ -1250,6 +1259,15 @@ <description>Please enter the description of this user action.</description> </action> +<action name="BadMessageTerminate_WC"> + <owner>nasko@chromium.org</owner> + <description> + Indicates that a renderer process was terminated due to receiving a + malformed or unexpected IPC message. The process was terminated by the + WebContentsImpl class. + </description> +</action> + <action name="BadMessageTerminate_WPH"> <owner>Please list the metric's owners. Add more owner tags as needed.</owner> <description>Please enter the description of this user action.</description>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 7b2a5f2..80a267a 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -6823,6 +6823,35 @@ </summary> </histogram> +<histogram name="Event.DragDrop.Cancel" enum="DragDropEventSource"> + <owner>mfomitchev@chromium.org</owner> + <summary> + Counts the number of times the user cancelled a drag and drop operation. + </summary> +</histogram> + +<histogram name="Event.DragDrop.Drop" enum="DragDropEventSource"> + <owner>mfomitchev@chromium.org</owner> + <summary> + Counts the number of times the user completed a drag and drop operation. + </summary> +</histogram> + +<histogram name="Event.DragDrop.ExternalOriginDrop"> + <owner>mfomitchev@chromium.org</owner> + <summary> + Counts the number of times a drag and drop operation originating outside of + a Chrome window successfuly drops. + </summary> +</histogram> + +<histogram name="Event.DragDrop.Start" enum="DragDropEventSource"> + <owner>mfomitchev@chromium.org</owner> + <summary> + Counts the number of times the user started a drag and drop operation. + </summary> +</histogram> + <histogram name="Event.Frequency.Renderer.FlingAnimate" units="hertz"> <owner>rbyers@chromium.org</owner> <summary> @@ -7183,9 +7212,8 @@ Time between input event creation and the renderer receiving and starting to process the event. For touch events on Windows, we measure from when the event reaches Chrome, whereas on other platforms we use the timestamp from - the kernel. On Windows, this metric is only reported when - |IsHighResNowFastAndReliable| is true, which will introduce some sampling - bias. + the kernel. On Windows, this metric is only reported when |IsHighResolution| + is true, which will introduce some sampling bias. </summary> </histogram> @@ -7196,8 +7224,7 @@ starting to process the event. For touch events on Windows, we measure from when the event reaches Chrome, whereas on other platforms we use the timestamp from the kernel. On Windows, this metric is only reported when - |IsHighResNowFastAndReliable| is true, which will introduce some sampling - bias. + |IsHighResolution| is true, which will introduce some sampling bias. </summary> </histogram> @@ -7220,8 +7247,8 @@ reaches the Impl thread. Maximum is 1000ms. On Windows, we measure from when the touch event reaches Chrome, whereas on other platforms we use the timestamp from the kernel. On Windows, this metric is only reported when - |IsHighResNowFastAndReliable| is true, which will introduce some sampling - bias. This supersedes the Event.Latency.RendererImpl.GestureScroll metric. + |IsHighResolution| is true, which will introduce some sampling bias. This + supersedes the Event.Latency.RendererImpl.GestureScroll metric. </summary> </histogram> @@ -14693,12 +14720,28 @@ </summary> </histogram> +<histogram name="Navigation.UI_OnCommitProvisionalLoad.Intent" + units="milliseconds"> + <owner>clamy@chromium.org</owner> + <summary> + Time between receiving an Android Intent and the navigation commit. + </summary> +</histogram> + <histogram name="Navigation.UI_OnCommitProvisionalLoad.Link" units="milliseconds"> <owner>clamy@chromium.org</owner> <summary>Time between clicking on a link and the navigation commit.</summary> </histogram> +<histogram name="Navigation.UI_OnLoadComplete.Intent" units="milliseconds"> + <owner>clamy@chromium.org</owner> + <summary> + Time between receiving an Android intent and the document load complete + event for a navigation in the main frame. + </summary> +</histogram> + <histogram name="Navigation.UI_OnLoadComplete.Link" units="milliseconds"> <owner>clamy@chromium.org</owner> <summary> @@ -18171,6 +18214,15 @@ </summary> </histogram> +<histogram name="Net.QuicSession.CookieSentToAccountsOverChannelId" + enum="BooleanUsage"> + <owner>rch@chromium.org</owner> + <summary> + Logs whether channel ID was used when a cookie is sent over QUIC to + https://accounts.google.com. + </summary> +</histogram> + <histogram name="Net.QuicSession.CreationError" enum="QuicSessionErrorCodes"> <owner>jar@chromium.org</owner> <owner>rch@chromium.org</owner> @@ -24651,6 +24703,86 @@ <summary>Temperature reading at sensor 9 (PECI) taken every 30s.</summary> </histogram> +<histogram name="Platform.Thermal.Temperature.Cpu.0" units="Celsius"> + <owner>mka@chromium.org</owner> + <summary> + Temperature reading at sensor 0 of the CPU collected every few seconds (may + vary between devices). + + This metric is specific to ChromeOS. + </summary> +</histogram> + +<histogram name="Platform.Thermal.Temperature.Wifi0" units="Celsius"> + <owner>mka@chromium.org</owner> + <summary> + Temperature reading at wireless interface 0 collected every few seconds (may + vary between devices). + + This metric is specific to ChromeOS. + </summary> +</histogram> + +<histogram name="Platform.Thermal.Temperature.Wifi1" units="Celsius"> + <owner>mka@chromium.org</owner> + <summary> + Temperature reading at wireless interface 1 collected every few seconds (may + vary between devices). + + This metric is specific to ChromeOS. + </summary> +</histogram> + +<histogram name="Platform.Thermal.Temperature.Wifi2" units="Celsius"> + <owner>mka@chromium.org</owner> + <summary> + Temperature reading at wireless interface 2 collected every few seconds (may + vary between devices). + + This metric is specific to ChromeOS. + </summary> +</histogram> + +<histogram name="Platform.Thermal.Zone.Cpu.States" units="Thermal state"> + <owner>mka@chromium.org</owner> + <summary> + State of the thermal zone of the CPU collected every second. State depends + on device, higher state corresponds to a higher temperature. + + This metric is specific to ChromeOS. + </summary> +</histogram> + +<histogram name="Platform.Thermal.Zone.Wifi0.States" units="Thermal state"> + <owner>mka@chromium.org</owner> + <summary> + State of the thermal zone of wireless interface 0 collected every second. + State depends on device, higher state corresponds to a higher temperature. + + This metric is specific to ChromeOS. + </summary> +</histogram> + +<histogram name="Platform.Thermal.Zone.Wifi1.States" units="Thermal state"> + <owner>mka@chromium.org</owner> + <summary> + State of the thermal zone of wireless interface 1 collected every second. + State depends on device, higher state corresponds to a higher temperature. + + This metric is specific to ChromeOS. + </summary> +</histogram> + +<histogram name="Platform.Thermal.Zone.Wifi2.States" units="Thermal state"> + <owner>mka@chromium.org</owner> + <summary> + State of the thermal zone of wireless interface 2 collected every second. + State depends on device, higher state corresponds to a higher temperature. + + This metric is specific to ChromeOS. + </summary> +</histogram> + <histogram name="Platform.TPM.DictionaryAttackCounter"> <owner>dkrahn@chromium.org</owner> <summary> @@ -28400,6 +28532,15 @@ <summary>Log each stage of a recovery component event.</summary> </histogram> +<histogram name="Render.Workers.MaxWorkerCountInRendererProcess"> + <owner>kinuko@chromium.org</owner> + <summary> + Maximum number of workers (SharedWorker or ServiceWorker) that are + simultaneously hosted in a single renderer process. Recorded when the + renderer process host is being destructed. + </summary> +</histogram> + <histogram name="Renderer.AcceleratedFixedRootBackground" enum="AcceleratedFixedRootBackground"> <owner>Please list the metric's owners. Add more owner tags as needed.</owner> @@ -44772,6 +44913,11 @@ <int value="4" label="Initiated by Resumption"/> </enum> +<enum name="DragDropEventSource" type="int"> + <int value="0" label="Mouse"/> + <int value="1" label="Touch"/> +</enum> + <enum name="DriveCacheDBOpenStatus" type="int"> <int value="0" label="Success"/> <int value="1" label="Corrupt database"/> @@ -46639,7 +46785,7 @@ <int value="774" label="NETWORKINGPRIVATE_GETNETWORKS"/> <int value="775" label="DELETED_WEBVIEW_SETNAME"/> <int value="776" label="ENTERPRISE_PLATFORMKEYSINTERNAL_GENERATEKEY"/> - <int value="777" label="ENTERPRISE_PLATFORMKEYSINTERNAL_SIGN"/> + <int value="777" label="PLATFORMKEYSINTERNAL_SIGN"/> <int value="778" label="ENTERPRISE_PLATFORMKEYSINTERNAL_GETTOKENS"/> <int value="779" label="ENTERPRISE_PLATFORMKEYS_GETCERTIFICATES"/> <int value="780" label="ENTERPRISE_PLATFORMKEYS_IMPORTCERTIFICATE"/> @@ -50282,6 +50428,7 @@ <int value="-1460462432" label="disable-media-source"/> <int value="-1433087548" label="enable-app-install-alerts"/> <int value="-1419788257" label="enable-experimental-hotwording"/> + <int value="-1411003295" label="disable-encrypted-media"/> <int value="-1408288176" label="enable-account-consistency"/> <int value="-1399753480" label="disable-harfbuzz-rendertext"/> <int value="-1399419572" label="enable-app-list"/> @@ -50456,6 +50603,7 @@ <int value="851085848" label="enable-settings-window"/> <int value="855746780" label="disable-physical-keyboard-autocorrect"/> <int value="857445869" label="enable-captive-portal-bypass-proxy"/> + <int value="867512869" label="mark-non-secure-as"/> <int value="869531646" label="enable-session-crashed-bubble"/> <int value="879699575" label="disable-gesture-tap-highlight"/> <int value="879992337" label="disable-pull-to-refresh-effect"/>
diff --git a/tools/perf/benchmarks/benchmark_unittest.py b/tools/perf/benchmarks/benchmark_unittest.py index fb4eae8..1b6cc10 100644 --- a/tools/perf/benchmarks/benchmark_unittest.py +++ b/tools/perf/benchmarks/benchmark_unittest.py
@@ -47,27 +47,6 @@ 'Multiple benchmarks with the same name %s are ' 'found: %s' % (n, str(names_to_benchmarks[n]))) -# Test all perf benchmarks explicitly define the Name() method and the name -# values are the same as the default one. -# TODO(nednguyen): remove this test after all perf benchmarks define Name() and -# checked in. -class TestPerfBenchmarkNames(unittest.TestCase): - def runTest(self): - all_benchmarks = _GetAllPerfBenchmarks() - - def BenchmarkName(cls): # Copy from Benchmark.Name()'s implementation - name = cls.__module__.split('.')[-1] - if hasattr(cls, 'tag'): - name += '.' + cls.tag - if hasattr(cls, 'page_set'): - name += '.' + cls.page_set.Name() - return name - - for b in all_benchmarks: - self.assertNotEquals(b.Name, benchmark_module.Benchmark.Name) - self.assertEquals(b.Name(), BenchmarkName(b)) - - def _AddBenchmarkOptionsTests(suite): # Using |index_by_class_name=True| allows returning multiple benchmarks # from a module. @@ -82,7 +61,6 @@ _BenchmarkOptionsTestGenerator(benchmark)) suite.addTest(BenchmarkOptionsTest(benchmark.Name())) suite.addTest(TestNoBenchmarkNamesDuplication()) - suite.addTest(TestPerfBenchmarkNames()) def load_tests(_, _2, _3):
diff --git a/tools/perf/benchmarks/inbox_benchmark.py b/tools/perf/benchmarks/inbox_benchmark.py index 5697a44..a79e87f 100644 --- a/tools/perf/benchmarks/inbox_benchmark.py +++ b/tools/perf/benchmarks/inbox_benchmark.py
@@ -2,14 +2,16 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -from page_sets import inbox -from telemetry import benchmark -from telemetry.web_perf import timeline_based_measurement - - -class Inbox(benchmark.Benchmark): - """Runs the timeline based measurement against inbox pageset.""" - test = timeline_based_measurement.TimelineBasedMeasurement - - def CreatePageSet(self, options): - return inbox.InboxPageSet() +# TODO: Benchmark is failing; see crbug.com/452257. Comment out instead of +# disabling because the failure happens before the Disabled check. +#from page_sets import inbox +#from telemetry import benchmark +#from telemetry.web_perf import timeline_based_measurement +# +#@benchmark.Disabled('android') +#class Inbox(benchmark.Benchmark): +# """Runs the timeline based measurement against inbox pageset.""" +# test = timeline_based_measurement.TimelineBasedMeasurement +# +# def CreatePageSet(self, options): +# return inbox.InboxPageSet()
diff --git a/tools/perf/benchmarks/session_restore.py b/tools/perf/benchmarks/session_restore.py index a12aeae..5c8ad2b 100644 --- a/tools/perf/benchmarks/session_restore.py +++ b/tools/perf/benchmarks/session_restore.py
@@ -42,11 +42,13 @@ is_cold = (self.tag == 'cold') return session_restore.SessionRestore(cold=is_cold) + def CreatePageSet(self, options): + return page_sets.Typical25PageSet(make_pages_with_no_interactions=True) + # crbug.com/325479, crbug.com/381990 @benchmark.Disabled('android', 'linux', 'reference') class SessionRestoreColdTypical25(_SessionRestoreTest): tag = 'cold' - page_set = page_sets.Typical25PageSet options = {'pageset_repeat': 5} @classmethod @@ -58,8 +60,8 @@ @benchmark.Disabled('android', 'linux', 'reference') class SessionRestoreWarmTypical25(_SessionRestoreTest): tag = 'warm' - page_set = page_sets.Typical25PageSet options = {'pageset_repeat': 20} + @classmethod def Name(cls): return 'session_restore.warm.typical_25'
diff --git a/tools/perf/measurements/screenshot.py b/tools/perf/measurements/screenshot.py deleted file mode 100644 index 37936f8..0000000 --- a/tools/perf/measurements/screenshot.py +++ /dev/null
@@ -1,42 +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. -import os - -from telemetry.image_processing import image_util -from telemetry.page import page_test -from telemetry.page import page_test -from telemetry.value import scalar - - -class Screenshot(page_test.PageTest): - def __init__(self, png_outdir): - super(Screenshot, self).__init__( - action_name_to_run = 'RunPageInteractions', - is_action_name_to_run_optional=True) - self._png_outdir = png_outdir - - def ValidateAndMeasurePage(self, page, tab, results): - if not tab.screenshot_supported: - raise page_test.TestNotSupportedOnPlatformError( - 'Browser does not support screenshotting') - - tab.WaitForDocumentReadyStateToBeComplete() - screenshot = tab.Screenshot(60) - - outpath = os.path.abspath( - os.path.join(self._png_outdir, page.file_safe_name)) + '.png' - - if os.path.exists(outpath): - previous_mtime = os.path.getmtime(outpath) - else: - previous_mtime = -1 - - image_util.WritePngFile(screenshot, outpath) - - saved_picture_count = 0 - if os.path.exists(outpath) and os.path.getmtime(outpath) > previous_mtime: - saved_picture_count = 1 - results.AddValue(scalar.ScalarValue( - results.current_page, 'saved_picture_count', 'count', - saved_picture_count))
diff --git a/tools/perf/measurements/screenshot_unittest.py b/tools/perf/measurements/screenshot_unittest.py deleted file mode 100644 index ac6e9be3..0000000 --- a/tools/perf/measurements/screenshot_unittest.py +++ /dev/null
@@ -1,37 +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. - -import logging -import shutil -import tempfile - -from measurements import screenshot -from telemetry import benchmark -from telemetry.page import page_test -from telemetry.unittest_util import options_for_unittests -from telemetry.unittest_util import page_test_test_case - - -class ScreenshotUnitTest(page_test_test_case.PageTestTestCase): - def setUp(self): - self._options = options_for_unittests.GetCopy() - self._png_outdir = tempfile.mkdtemp('_png_test') - - def tearDown(self): - shutil.rmtree(self._png_outdir) - - @benchmark.Disabled('win') # http://crbug.com/386572 - def testScreenshot(self): - ps = self.CreatePageSetFromFileInUnittestDataDir('blank.html') - measurement = screenshot.Screenshot(self._png_outdir) - try: - results = self.RunMeasurement(measurement, ps, options=self._options) - except page_test.TestNotSupportedOnPlatformError as e: - logging.warning(e) - return - - saved_picture_count = results.FindAllPageSpecificValuesNamed( - 'saved_picture_count') - self.assertEquals(len(saved_picture_count), 1) - self.assertGreater(saved_picture_count[0].GetRepresentativeNumber(), 0)
diff --git a/tools/perf/measurements/session_restore.py b/tools/perf/measurements/session_restore.py index d69c958..06e570c 100644 --- a/tools/perf/measurements/session_restore.py +++ b/tools/perf/measurements/session_restore.py
@@ -19,7 +19,7 @@ see startup.py for details. """ - def __init__(self, cold=False, action_name_to_run = ''): + def __init__(self, cold=False, action_name_to_run='RunPageInteractions'): super(SessionRestore, self).__init__(cold=cold, action_name_to_run=action_name_to_run) self.close_tabs_before_run = False
diff --git a/tools/perf/measurements/startup.py b/tools/perf/measurements/startup.py index 6dfdc5a..aa6ad16 100644 --- a/tools/perf/measurements/startup.py +++ b/tools/perf/measurements/startup.py
@@ -16,7 +16,7 @@ repeat the page set to ensure it's cached. """ - def __init__(self, cold=False, action_name_to_run=''): + def __init__(self, cold=False, action_name_to_run='RunPageInteractions'): super(Startup, self).__init__(needs_browser_restart_after_each_page=True, action_name_to_run=action_name_to_run) self._cold = cold
diff --git a/tools/perf/page_sets/typical_25.py b/tools/perf/page_sets/typical_25.py index 89395a39..57983bb55 100644 --- a/tools/perf/page_sets/typical_25.py +++ b/tools/perf/page_sets/typical_25.py
@@ -7,12 +7,15 @@ class Typical25Page(page_module.Page): - def __init__(self, url, page_set): + def __init__(self, url, page_set, run_no_page_interactions): super(Typical25Page, self).__init__(url=url, page_set=page_set) self.user_agent_type = 'desktop' self.archive_data_file = 'data/typical_25.json' + self._run_no_page_interactions = run_no_page_interactions def RunPageInteractions(self, action_runner): + if self._run_no_page_interactions: + return interaction = action_runner.BeginGestureInteraction( 'ScrollAction', is_smooth=True) action_runner.ScrollPage() @@ -23,7 +26,7 @@ """ Pages designed to represent the median, not highly optimized web """ - def __init__(self): + def __init__(self, make_pages_with_no_interactions=False): super(Typical25PageSet, self).__init__( user_agent_type='desktop', archive_data_file='data/typical_25.json', @@ -71,4 +74,5 @@ ] for url in urls_list: - self.AddUserStory(Typical25Page(url, self)) + self.AddUserStory( + Typical25Page(url, self, make_pages_with_no_interactions))
diff --git a/tools/telemetry/telemetry/benchmark.py b/tools/telemetry/telemetry/benchmark.py index f32a1fd..2ef5fa4b 100644 --- a/tools/telemetry/telemetry/benchmark.py +++ b/tools/telemetry/telemetry/benchmark.py
@@ -33,9 +33,10 @@ class BenchmarkMetadata(object): - def __init__(self, name, description=''): + def __init__(self, name, description='', rerun_options=None): self._name = name self._description = description + self._rerun_options = rerun_options @property def name(self): @@ -45,6 +46,10 @@ def description(self): return self._description + @property + def rerun_options(self): + return self._rerun_options + class Benchmark(command_line.Command): """Base class for a Telemetry benchmark. @@ -77,21 +82,49 @@ @classmethod def Name(cls): - name = cls.__module__.split('.')[-1] - if hasattr(cls, 'tag'): - name += '.' + cls.tag - if hasattr(cls, 'page_set'): - name += '.' + cls.page_set.Name() - return name + return '%s.%s' % (cls.__module__.split('.')[-1], cls.__name__) @classmethod def AddCommandLineArgs(cls, parser): + group = optparse.OptionGroup(parser, '%s test options' % cls.Name()) if hasattr(cls, 'AddBenchmarkCommandLineArgs'): - group = optparse.OptionGroup(parser, '%s test options' % cls.Name()) cls.AddBenchmarkCommandLineArgs(group) + + if cls.HasTraceRerunDebugOption(): + group.add_option( + '--rerun-with-debug-trace', + action='store_true', + help='Rerun option that enables more extensive tracing.') + + if group.option_list: parser.add_option_group(group) @classmethod + def HasTraceRerunDebugOption(cls): + if hasattr(cls, 'HasBenchmarkTraceRerunDebugOption'): + if cls.HasBenchmarkTraceRerunDebugOption(): + return True + return False + + def GetTraceRerunCommands(self): + if self.HasTraceRerunDebugOption(): + return [['Debug Trace', '--rerun-with-debug-trace']] + return [] + + def SetupTraceRerunOptions(self, browser_options, tbm_options): + if self.HasTraceRerunDebugOption(): + if browser_options.rerun_with_debug_trace: + self.SetupBenchmarkDebugTraceRerunOptions(tbm_options) + else: + self.SetupBenchmarkDefaultTraceRerunOptions(tbm_options) + + def SetupBenchmarkDefaultTraceRerunOptions(self, tbm_options): + """Setup tracing categories associated with default trace option.""" + + def SetupBenchmarkDebugTraceRerunOptions(self, tbm_options): + """Setup tracing categories associated with debug trace option.""" + + @classmethod def SetArgumentDefaults(cls, parser): default_values = parser.get_default_values() invalid_options = [ @@ -109,7 +142,8 @@ """Add browser options that are required by this benchmark.""" def GetMetadata(self): - return BenchmarkMetadata(self.Name(), self.__doc__) + return BenchmarkMetadata( + self.Name(), self.__doc__, self.GetTraceRerunCommands()) def Run(self, finder_options): """Run this test with the given options. @@ -253,8 +287,10 @@ 'Cannot override CreateTimelineBasedMeasurementOptions ' 'with a PageTest.') return self.test() # pylint: disable=no-value-for-parameter - return timeline_based_measurement.TimelineBasedMeasurement( - self.CreateTimelineBasedMeasurementOptions()) + + opts = self.CreateTimelineBasedMeasurementOptions() + self.SetupTraceRerunOptions(options, opts) + return timeline_based_measurement.TimelineBasedMeasurement(opts) def CreatePageSet(self, options): # pylint: disable=unused-argument """Get the page set this test will run on.
diff --git a/tools/telemetry/telemetry/core/android_app_unittest.py b/tools/telemetry/telemetry/core/android_app_unittest.py index 2021625..4b2af1a0 100644 --- a/tools/telemetry/telemetry/core/android_app_unittest.py +++ b/tools/telemetry/telemetry/core/android_app_unittest.py
@@ -16,11 +16,11 @@ class AndroidAppTest(unittest.TestCase): def setUp(self): - options = options_for_unittests.GetCopy() - self._device = android_device.GetDevice(options) + self._options = options_for_unittests.GetCopy() + self._device = android_device.GetDevice(self._options) def CreateAndroidApp(self, start_intent): - platform = platform_module.GetPlatformForDevice(self._device) + platform = platform_module.GetPlatformForDevice(self._device, self._options) platform_backend = platform._platform_backend app_backend = android_app_backend.AndroidAppBackend( platform_backend, start_intent)
diff --git a/tools/telemetry/telemetry/core/backends/android_command_line_backend.py b/tools/telemetry/telemetry/core/backends/android_command_line_backend.py index e2c3e1a1..e05c0bb 100644 --- a/tools/telemetry/telemetry/core/backends/android_command_line_backend.py +++ b/tools/telemetry/telemetry/core/backends/android_command_line_backend.py
@@ -63,7 +63,7 @@ self._adb = adb self._backend_settings = backend_settings self._startup_args = startup_args - self._saved_command_line_file_contents = '' + self._saved_command_line_file_contents = None @property def command_line_file(self): @@ -79,20 +79,32 @@ # be a Telemetry created one. This is to prevent a common bug where # --host-resolver-rules borks people's browsers if something goes wrong # with Telemetry. - self._saved_command_line_file_contents = ''.join(self._ReadFile()) + self._saved_command_line_file_contents = self._ReadFile() if '--host-resolver-rules' in self._saved_command_line_file_contents: - self._saved_command_line_file_contents = '' - self._WriteFile(content) + self._saved_command_line_file_contents = None except device_errors.CommandFailedError: + self._saved_command_line_file_contents = None + + try: + self._WriteFile(content) + except device_errors.CommandFailedError as exc: + logging.critical(exc) logging.critical('Cannot set Chrome command line. ' 'Fix this by flashing to a userdebug build.') sys.exit(1) def RestoreCommandLineFlags(self): - self._WriteFile(self._saved_command_line_file_contents) + if self._saved_command_line_file_contents is None: + self._RemoveFile() + else: + self._WriteFile(self._saved_command_line_file_contents) def _ReadFile(self): - return self._adb.device().ReadFile(self.command_line_file) + return self._adb.device().ReadFile(self.command_line_file, as_root=True) def _WriteFile(self, contents): self._adb.device().WriteFile(self.command_line_file, contents, as_root=True) + + def _RemoveFile(self): + self._adb.device().RunShellCommand(['rm', '-f', self.command_line_file], + as_root=True, check_return=True)
diff --git a/tools/telemetry/telemetry/core/backends/android_command_line_backend_unittest.py b/tools/telemetry/telemetry/core/backends/android_command_line_backend_unittest.py index 4e7b5294..b7ec6a93 100644 --- a/tools/telemetry/telemetry/core/backends/android_command_line_backend_unittest.py +++ b/tools/telemetry/telemetry/core/backends/android_command_line_backend_unittest.py
@@ -2,10 +2,22 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import logging import unittest +from telemetry import benchmark +from telemetry.core.backends import adb_commands from telemetry.core.backends import android_command_line_backend +class _MockBackendSettings(object): + pseudo_exec_name = 'chrome' + + def __init__(self, path): + self._path = path + + def GetCommandLineFile(self, _is_user_debug_build): + return self._path + class AndroidCommandLineBackendTest(unittest.TestCase): @@ -29,3 +41,43 @@ expected_output = "key='valueA valueB'" self.assertEqual(expected_output, android_command_line_backend._QuoteIfNeeded(string)) + + @benchmark.Enabled('android') + def testSetUpCommandLineFlagsCmdRestored(self): + """Test that a previous command line file is restored. + + Requires a device connected to the host. + """ + serial = adb_commands.GetAttachedDevices()[0] + cmd_file = '/data/local/tmp/test_cmd' + adb = adb_commands.AdbCommands(device=serial) + backend_settings = _MockBackendSettings('/data/local/tmp/test_cmd') + startup_args = ['--some', '--test', '--args'] + device = adb.device() + device.WriteFile(cmd_file, 'chrome --args --to --save') + with android_command_line_backend.SetUpCommandLineFlags( + adb, backend_settings, startup_args): + self.assertEqual('chrome --some --test --args', + device.ReadFile(cmd_file).strip()) + self.assertEqual('chrome --args --to --save', + device.ReadFile(cmd_file).strip()) + device.RunShellCommand(['rm', '-f', cmd_file], check_return=True) + + @benchmark.Enabled('android') + def testSetUpCommandLineFlagsCmdRemoved(self): + """Test that the command line file is removed if it did not exist before. + + Requires a device connected to the host. + """ + serial = adb_commands.GetAttachedDevices()[0] + cmd_file = '/data/local/tmp/test_cmd' + adb = adb_commands.AdbCommands(device=serial) + backend_settings = _MockBackendSettings('/data/local/tmp/test_cmd') + startup_args = ['--some', '--test', '--args'] + device = adb.device() + device.RunShellCommand(['rm', '-f', cmd_file], check_return=True) + with android_command_line_backend.SetUpCommandLineFlags( + adb, backend_settings, startup_args): + self.assertEqual('chrome --some --test --args', + device.ReadFile(cmd_file).strip()) + self.assertFalse(device.FileExists(cmd_file))
diff --git a/tools/telemetry/telemetry/core/backends/chrome/android_browser_backend.py b/tools/telemetry/telemetry/core/backends/chrome/android_browser_backend.py index 6e9f6521..227bc3bf 100644 --- a/tools/telemetry/telemetry/core/backends/chrome/android_browser_backend.py +++ b/tools/telemetry/telemetry/core/backends/chrome/android_browser_backend.py
@@ -25,8 +25,8 @@ class AndroidBrowserBackend(chrome_browser_backend.ChromeBrowserBackend): """The backend for controlling a browser instance running on Android.""" def __init__(self, android_platform_backend, browser_options, - backend_settings, use_rndis_forwarder, output_profile_path, - extensions_to_load, target_arch): + backend_settings, output_profile_path, extensions_to_load, + target_arch): assert isinstance(android_platform_backend, android_platform_backend_module.AndroidPlatformBackend) super(AndroidBrowserBackend, self).__init__( @@ -64,13 +64,9 @@ self._backend_settings.package, self._backend_settings.profile_ignore_list) - # Configure platform to use the rndis forwarder. - # TODO(ariblue): Move this setting out of a browser-specific path, since - # apps may want to use the forwarder, as well. - self._platform_backend.SetRndisForwarder(use_rndis_forwarder) - - if self.browser_options.netsim or use_rndis_forwarder: - assert use_rndis_forwarder, 'Netsim requires RNDIS forwarding.' + if self.browser_options.netsim: + assert self.platform_backend.use_rndis_forwarder, ( + 'Netsim requires RNDIS forwarding.') self.wpr_port_pairs = forwarders.PortPairs( http=forwarders.PortPair(0, 80), https=forwarders.PortPair(0, 443),
diff --git a/tools/telemetry/telemetry/core/backends/chrome/android_browser_finder.py b/tools/telemetry/telemetry/core/backends/chrome/android_browser_finder.py index 68322db..40e84ff 100644 --- a/tools/telemetry/telemetry/core/backends/chrome/android_browser_finder.py +++ b/tools/telemetry/telemetry/core/backends/chrome/android_browser_finder.py
@@ -107,14 +107,9 @@ def Create(self, finder_options): self._InitPlatformIfNeeded() - - use_rndis_forwarder = (finder_options.android_rndis or - finder_options.browser_options.netsim or - platform.GetHostPlatform().GetOSName() != 'linux') browser_backend = android_browser_backend.AndroidBrowserBackend( self._platform_backend, finder_options.browser_options, self._backend_settings, - use_rndis_forwarder, output_profile_path=finder_options.output_profile_path, extensions_to_load=finder_options.extensions_to_load, target_arch=finder_options.target_arch) @@ -214,5 +209,5 @@ device = android_device.GetDevice(finder_options) if not device: return [] - android_platform = platform.GetPlatformForDevice(device) + android_platform = platform.GetPlatformForDevice(device, finder_options) return _FindAllPossibleBrowsers(finder_options, android_platform)
diff --git a/tools/telemetry/telemetry/core/backends/chrome/cros_browser_backend.py b/tools/telemetry/telemetry/core/backends/chrome/cros_browser_backend.py index 9cec8902..489a7a7 100644 --- a/tools/telemetry/telemetry/core/backends/chrome/cros_browser_backend.py +++ b/tools/telemetry/telemetry/core/backends/chrome/cros_browser_backend.py
@@ -156,7 +156,7 @@ self._cri.RestartUI(False) # Logs out. self._cri.CloseConnection() - util.WaitFor(lambda: not self._IsCryptohomeMounted(), 30) + util.WaitFor(lambda: not self._IsCryptohomeMounted(), 180) if self._forwarder: self._forwarder.Close()
diff --git a/tools/telemetry/telemetry/core/backends/chrome/cros_browser_finder.py b/tools/telemetry/telemetry/core/backends/chrome/cros_browser_finder.py index 7ea3dea..6c57c975 100644 --- a/tools/telemetry/telemetry/core/backends/chrome/cros_browser_finder.py +++ b/tools/telemetry/telemetry/core/backends/chrome/cros_browser_finder.py
@@ -106,7 +106,7 @@ finder_options.cros_ssh_identity) # Check ssh try: - platform = platform_module.GetPlatformForDevice(device) + platform = platform_module.GetPlatformForDevice(device, finder_options) except cros_interface.LoginException, ex: if isinstance(ex, cros_interface.KeylessLoginRequiredException): logging.warn('Could not ssh into %s. Your device must be configured',
diff --git a/tools/telemetry/telemetry/core/backends/chrome_inspector/devtools_client_backend.py b/tools/telemetry/telemetry/core/backends/chrome_inspector/devtools_client_backend.py index 9635637..4dc7f75 100644 --- a/tools/telemetry/telemetry/core/backends/chrome_inspector/devtools_client_backend.py +++ b/tools/telemetry/telemetry/core/backends/chrome_inspector/devtools_client_backend.py
@@ -18,9 +18,11 @@ return _IsDevToolsAgentAvailable(devtools_http.DevToolsHttp(port)) +# TODO(nednguyen): Find a more reliable way to check whether the devtool agent +# is still alive. def _IsDevToolsAgentAvailable(devtools_http_instance): try: - devtools_http_instance.Request('', timeout=.1) + devtools_http_instance.Request('') except devtools_http.DevToolsClientConnectionError: return False else:
diff --git a/tools/telemetry/telemetry/core/backends/chrome_inspector/inspector_network_unittest.py b/tools/telemetry/telemetry/core/backends/chrome_inspector/inspector_network_unittest.py index 5fccf1b..551716e4 100644 --- a/tools/telemetry/telemetry/core/backends/chrome_inspector/inspector_network_unittest.py +++ b/tools/telemetry/telemetry/core/backends/chrome_inspector/inspector_network_unittest.py
@@ -32,7 +32,7 @@ self.assertTrue(self._tab.timeline_model) return self._tab.timeline_model.GetAllEventsOfName('HTTPResponse') - @decorators.Disabled('mavericks') # crbug.com/449979. + @decorators.Disabled('mac') # crbug.com/449979. def testHTTPResponseTimelineRecorder(self): tests = { 'blank.html': InspectorNetworkTabTest.TestCase(),
diff --git a/tools/telemetry/telemetry/core/forwarders/android_forwarder.py b/tools/telemetry/telemetry/core/forwarders/android_forwarder.py index c5ef45d..19f5132 100644 --- a/tools/telemetry/telemetry/core/forwarders/android_forwarder.py +++ b/tools/telemetry/telemetry/core/forwarders/android_forwarder.py
@@ -231,7 +231,7 @@ """Returns the name of the host-side network interface.""" interface_list = self._EnumerateHostInterfaces() ether_address = self._device.ReadFile( - '%s/f_rndis/ethaddr' % self._RNDIS_DEVICE)[0] + '%s/f_rndis/ethaddr' % self._RNDIS_DEVICE).strip() interface_name = None for line in interface_list: if not line.startswith((' ', '\t')): @@ -322,7 +322,7 @@ self._device.RunShellCommand('rm %s.log' % script_prefix) self._device.RunShellCommand('. %s.sh' % script_prefix) self._WaitForDevice() - result = self._device.ReadFile('%s.log' % script_prefix) + result = self._device.ReadFile('%s.log' % script_prefix).splitlines() assert any('DONE' in line for line in result), 'RNDIS script did not run!' def _CheckEnableRndis(self, force):
diff --git a/tools/telemetry/telemetry/core/platform/__init__.py b/tools/telemetry/telemetry/core/platform/__init__.py index c4ef84c..a4cb604 100644 --- a/tools/telemetry/telemetry/core/platform/__init__.py +++ b/tools/telemetry/telemetry/core/platform/__init__.py
@@ -43,7 +43,7 @@ platform_backend_module.PlatformBackend).itervalues() -def GetPlatformForDevice(device, logging=real_logging): +def GetPlatformForDevice(device, finder_options, logging=real_logging): """ Returns a platform instance for the device. Args: device: a device.Device instance. @@ -54,7 +54,8 @@ for platform_backend_class in _IterAllPlatformBackendClasses(): if platform_backend_class.SupportsDevice(device): _remote_platforms[device.guid] = ( - platform_backend_class.CreatePlatformForDevice(device)) + platform_backend_class.CreatePlatformForDevice(device, + finder_options)) return _remote_platforms[device.guid] return None except Exception: @@ -71,6 +72,7 @@ """ def __init__(self, platform_backend): self._platform_backend = platform_backend + self._platform_backend.InitPlatformBackend() self._platform_backend.SetPlatform(self) self._network_controller = network_controller.NetworkController( self._platform_backend.network_controller_backend)
diff --git a/tools/telemetry/telemetry/core/platform/android_platform_backend.py b/tools/telemetry/telemetry/core/platform/android_platform_backend.py index f8e82514..3d7132ef 100644 --- a/tools/telemetry/telemetry/core/platform/android_platform_backend.py +++ b/tools/telemetry/telemetry/core/platform/android_platform_backend.py
@@ -16,6 +16,7 @@ from telemetry.core import video from telemetry.core.backends import adb_commands from telemetry.core.forwarders import android_forwarder +from telemetry.core import platform from telemetry.core.platform import android_device from telemetry.core.platform import android_platform from telemetry.core.platform import linux_based_platform_backend @@ -26,7 +27,9 @@ from telemetry.core.platform.power_monitor import power_monitor_controller from telemetry.core.platform.profiler import android_prebuilt_profiler_helper from telemetry.util import exception_formatter +from telemetry.util import external_modules +psutil = external_modules.ImportOptionalModule('psutil') util.AddDirToPythonPath(util.GetChromiumSrcDir(), 'third_party', 'webpagereplay') import adb_install_cert # pylint: disable=F0401 @@ -45,15 +48,10 @@ except Exception: surface_stats_collector = None -try: - import psutil # pylint: disable=import-error -except ImportError: - psutil = None - class AndroidPlatformBackend( linux_based_platform_backend.LinuxBasedPlatformBackend): - def __init__(self, device): + def __init__(self, device, finder_options): assert device, ( 'AndroidPlatformBackend can only be initialized from remote device') super(AndroidPlatformBackend, self).__init__(device) @@ -90,7 +88,11 @@ self._wpr_ca_cert_path = None self._device_cert_util = None self._is_test_ca_installed = False - self._use_rndis_forwarder = False + + self._use_rndis_forwarder = ( + finder_options.android_rndis or + finder_options.browser_options.netsim or + platform.GetHostPlatform().GetOSName() != 'linux') _FixPossibleAdbInstability() @@ -99,9 +101,10 @@ return isinstance(device, android_device.AndroidDevice) @classmethod - def CreatePlatformForDevice(cls, device): + def CreatePlatformForDevice(cls, device, finder_options): assert cls.SupportsDevice(device) - return android_platform.AndroidPlatform(AndroidPlatformBackend(device)) + platform_backend = AndroidPlatformBackend(device, finder_options) + return android_platform.AndroidPlatform(platform_backend) @property def forwarder_factory(self): @@ -111,10 +114,9 @@ return self._forwarder_factory - def SetRndisForwarder(self, use_rndis_forwarder): - assert self._forwarder_factory is None, ( - 'Cannot switch to use rndis forwarding after forwarder is created.') - self._use_rndis_forwarder = use_rndis_forwarder + @property + def use_rndis_forwarder(self): + return self._use_rndis_forwarder @property def adb(self): @@ -347,7 +349,7 @@ if not self._can_access_protected_file_contents: logging.warning('%s cannot be retrieved on non-rooted device.' % fname) return '' - return '\n'.join(self._device.ReadFile(fname, as_root=True)) + return self._device.ReadFile(fname, as_root=True) def GetPsOutput(self, columns, pid=None): assert columns == ['pid', 'name'] or columns == ['pid'], \ @@ -637,13 +639,9 @@ for process in psutil.process_iter(): try: if 'adb' in process.name: - if 'cpu_affinity' in dir(process): - process.cpu_affinity([0]) # New versions of psutil. - elif 'set_cpu_affinity' in dir(process): + if 'set_cpu_affinity' in dir(process): process.set_cpu_affinity([0]) # Older versions. else: - logging.warn( - 'Cannot set CPU affinity due to stale psutil version: %s', - '.'.join(str(x) for x in psutil.version_info)) + process.cpu_affinity([0]) # New versions of psutil. except (psutil.NoSuchProcess, psutil.AccessDenied): logging.warn('Failed to set adb process CPU affinity')
diff --git a/tools/telemetry/telemetry/core/platform/android_platform_backend_unittest.py b/tools/telemetry/telemetry/core/platform/android_platform_backend_unittest.py index 43e9f72..4d19ff28 100644 --- a/tools/telemetry/telemetry/core/platform/android_platform_backend_unittest.py +++ b/tools/telemetry/telemetry/core/platform/android_platform_backend_unittest.py
@@ -8,10 +8,12 @@ from telemetry.core.platform import android_device from telemetry.core.platform import android_platform_backend from telemetry.unittest_util import system_stub +from telemetry.unittest_util import options_for_unittests class AndroidPlatformBackendTest(unittest.TestCase): def setUp(self): + self._options = options_for_unittests.GetCopy() self._stubs = system_stub.Override( android_platform_backend, ['perf_control', 'thermal_throttle', 'adb_commands', 'certutils', @@ -27,17 +29,17 @@ @decorators.Disabled('chromeos') def testGetCpuStats(self): - proc_stat_content = [ + proc_stat_content = ( '7702 (.android.chrome) S 167 167 0 0 -1 1077936448 ' '3247 0 0 0 4 1 0 0 20 0 9 0 5603962 337379328 5867 ' '4294967295 1074458624 1074463824 3197495984 3197494152 ' '1074767676 0 4612 0 38136 4294967295 0 0 17 0 0 0 0 0 0 ' - '1074470376 1074470912 1102155776'] + '1074470376 1074470912 1102155776\n') self._stubs.adb_commands.adb_device.mock_content = proc_stat_content old_interface = self._stubs.adb_commands.adb_device.old_interface old_interface.can_access_protected_file_contents = True backend = android_platform_backend.AndroidPlatformBackend( - android_device.AndroidDevice('12345')) + android_device.AndroidDevice('12345'), self._options) cpu_stats = backend.GetCpuStats('7702') self.assertEquals(cpu_stats, {'CpuProcessTime': 0.05}) @@ -45,7 +47,7 @@ def testGetCpuStatsInvalidPID(self): # Mock an empty /proc/pid/stat. backend = android_platform_backend.AndroidPlatformBackend( - android_device.AndroidDevice('1234')) + android_device.AndroidDevice('1234'), self._options) cpu_stats = backend.GetCpuStats('7702') self.assertEquals(cpu_stats, {}) @@ -74,12 +76,12 @@ def testInstallTestCaFailure(self): backend = android_platform_backend.AndroidPlatformBackend( - android_device.AndroidDevice('failure')) + android_device.AndroidDevice('failure'), self._options) backend.InstallTestCa() self.assertFalse(backend.is_test_ca_installed) def testInstallTestCaSuccess(self): backend = android_platform_backend.AndroidPlatformBackend( - android_device.AndroidDevice('success')) + android_device.AndroidDevice('success'), self._options) backend.InstallTestCa() self.assertTrue(backend.is_test_ca_installed)
diff --git a/tools/telemetry/telemetry/core/platform/cros_platform_backend.py b/tools/telemetry/telemetry/core/platform/cros_platform_backend.py index 32da60d..cb7f69c 100644 --- a/tools/telemetry/telemetry/core/platform/cros_platform_backend.py +++ b/tools/telemetry/telemetry/core/platform/cros_platform_backend.py
@@ -33,7 +33,7 @@ return isinstance(device, cros_device.CrOSDevice) @classmethod - def CreatePlatformForDevice(cls, device): + def CreatePlatformForDevice(cls, device, finder_options): assert cls.SupportsDevice(device) return platform.Platform(CrosPlatformBackend(device))
diff --git a/tools/telemetry/telemetry/core/platform/platform_backend.py b/tools/telemetry/telemetry/core/platform/platform_backend.py index 9855a9c732..26f6da4 100644 --- a/tools/telemetry/telemetry/core/platform/platform_backend.py +++ b/tools/telemetry/telemetry/core/platform/platform_backend.py
@@ -60,11 +60,15 @@ raise ValueError('Unsupported device: %s' % device.name) self._platform = None self._running_browser_backends = weakref.WeakSet() + self._network_controller_backend = None + self._tracing_controller_backend = None + self._forwarder_factory = None + + def InitPlatformBackend(self): self._network_controller_backend = ( network_controller_backend.NetworkControllerBackend(self)) self._tracing_controller_backend = ( tracing_controller_backend.TracingControllerBackend(self)) - self._forwarder_factory = None @classmethod def IsPlatformBackendForHost(cls): @@ -79,7 +83,7 @@ return False @classmethod - def CreatePlatformForDevice(cls, device): + def CreatePlatformForDevice(cls, device, finder_options): raise NotImplementedError def SetPlatform(self, platform):
diff --git a/tools/telemetry/telemetry/core/platform/power_monitor/android_temperature_monitor.py b/tools/telemetry/telemetry/core/platform/power_monitor/android_temperature_monitor.py index fa56bab..2b61e628 100644 --- a/tools/telemetry/telemetry/core/platform/power_monitor/android_temperature_monitor.py +++ b/tools/telemetry/telemetry/core/platform/power_monitor/android_temperature_monitor.py
@@ -2,7 +2,15 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import telemetry.core.platform.power_monitor as power_monitor +from telemetry.core import util +from telemetry.core.platform import power_monitor + +util.AddDirToPythonPath(util.GetChromiumSrcDir(), 'build', 'android') +try: + from pylib.device import device_errors # pylint: disable=F0401 +except ImportError: + device_errors = None + _TEMPERATURE_FILE = '/sys/class/thermal/thermal_zone0/temp' @@ -57,7 +65,8 @@ return power_data def _GetBoardTemperatureCelsius(self): - contents = self._device.ReadFile(_TEMPERATURE_FILE) - if len(contents) > 0: - return float(contents[0]) - return None + try: + contents = self._device.ReadFile(_TEMPERATURE_FILE) + return float(contents) if contents else None + except device_errors.CommandFailedError: + return None
diff --git a/tools/telemetry/telemetry/core/platform/power_monitor/android_temperature_monitor_unittest.py b/tools/telemetry/telemetry/core/platform/power_monitor/android_temperature_monitor_unittest.py index 0b4c2a6..ea283ac 100644 --- a/tools/telemetry/telemetry/core/platform/power_monitor/android_temperature_monitor_unittest.py +++ b/tools/telemetry/telemetry/core/platform/power_monitor/android_temperature_monitor_unittest.py
@@ -61,7 +61,7 @@ mock_power_monitor.ExpectCall('CanMonitorPower').WillReturn(False) mock_adb = simple_mock.MockObject() mock_device_utils = simple_mock.MockObject() - mock_device_utils.ExpectCall('ReadFile', _).WillReturn([]) + mock_device_utils.ExpectCall('ReadFile', _).WillReturn('') setattr(mock_device_utils, 'old_interface', mock_adb) monitor = android_temperature_monitor.AndroidTemperatureMonitor(
diff --git a/tools/telemetry/telemetry/core/platform/profiler/android_profiling_helper_unittest.py b/tools/telemetry/telemetry/core/platform/profiler/android_profiling_helper_unittest.py index c77e23e..fd31de3 100644 --- a/tools/telemetry/telemetry/core/platform/profiler/android_profiling_helper_unittest.py +++ b/tools/telemetry/telemetry/core/platform/profiler/android_profiling_helper_unittest.py
@@ -20,7 +20,7 @@ libs = set() for pid in pids: maps_file = '/proc/%d/maps' % pid - maps = device.ReadFile(maps_file, as_root=True) + maps = device.ReadFile(maps_file, as_root=True).splitlines() for map_line in maps: lib = re.match(r'.*\s(/.*[.]so)$', map_line) if lib:
diff --git a/tools/telemetry/telemetry/core/platform/tracing_agent/display_tracing_agent.py b/tools/telemetry/telemetry/core/platform/tracing_agent/display_tracing_agent.py index 3ae0ebb..1beaad54 100644 --- a/tools/telemetry/telemetry/core/platform/tracing_agent/display_tracing_agent.py +++ b/tools/telemetry/telemetry/core/platform/tracing_agent/display_tracing_agent.py
@@ -20,7 +20,6 @@ return True def Stop(self, trace_data_builder): - assert self._is_tracing_running surface_flinger_trace_data = self._platform_backend.StopDisplayTracing() trace_data_builder.AddEventsTo( trace_data.SURFACE_FLINGER_PART, surface_flinger_trace_data)
diff --git a/tools/telemetry/telemetry/core/platform/tracing_controller_backend.py b/tools/telemetry/telemetry/core/platform/tracing_controller_backend.py index 980841f..98dbd57 100644 --- a/tools/telemetry/telemetry/core/platform/tracing_controller_backend.py +++ b/tools/telemetry/telemetry/core/platform/tracing_controller_backend.py
@@ -15,8 +15,8 @@ def _IterAllTracingAgentClasses(): - tracing_agent_dir = os.path.dirname(os.path.join( - os.path.realpath(__file__), 'tracing_agent')) + tracing_agent_dir = os.path.join( + os.path.dirname(os.path.realpath(__file__)), 'tracing_agent') return discover.DiscoverClasses( tracing_agent_dir, util.GetTelemetryDir(), tracing_agent.TracingAgent).itervalues()
diff --git a/tools/telemetry/telemetry/page/page_run_end_to_end_unittest.py b/tools/telemetry/telemetry/page/page_run_end_to_end_unittest.py index e1fc7a32..4d14b0a 100644 --- a/tools/telemetry/telemetry/page/page_run_end_to_end_unittest.py +++ b/tools/telemetry/telemetry/page/page_run_end_to_end_unittest.py
@@ -140,6 +140,37 @@ self.assertEquals(1, len(GetSuccessfulPageRuns(results))) self.assertEquals(1, len(results.failures)) + def testNeedsBrowserRestartAfterEachPage(self): + self.SuppressExceptionFormatting() + ps = page_set.PageSet() + expectations = test_expectations.TestExpectations() + ps.pages.append(page_module.Page( + 'file://blank.html', ps, base_dir=util.GetUnittestDataDir())) + ps.pages.append(page_module.Page( + 'file://blank.html', ps, base_dir=util.GetUnittestDataDir())) + + class Test(page_test.PageTest): + def __init__(self, *args, **kwargs): + super(Test, self).__init__(*args, **kwargs) + self.browser_starts = 0 + + def DidStartBrowser(self, *args): + super(Test, self).DidStartBrowser(*args) + self.browser_starts += 1 + + def ValidateAndMeasurePage(self, page, tab, results): + pass + + options = options_for_unittests.GetCopy() + options.output_formats = ['none'] + options.suppress_gtest_report = True + test = Test(needs_browser_restart_after_each_page=True) + SetUpUserStoryRunnerArguments(options) + results = results_options.CreateResults(EmptyMetadataForTest(), options) + user_story_runner.Run(test, ps, expectations, options, results) + self.assertEquals(2, len(GetSuccessfulPageRuns(results))) + self.assertEquals(2, test.browser_starts) + def testHandlingOfCrashedTabWithExpectedFailure(self): self.SuppressExceptionFormatting() ps = page_set.PageSet()
diff --git a/tools/telemetry/telemetry/page/page_test.py b/tools/telemetry/telemetry/page/page_test.py index d661678..646a5f4 100644 --- a/tools/telemetry/telemetry/page/page_test.py +++ b/tools/telemetry/telemetry/page/page_test.py
@@ -47,19 +47,13 @@ subclasses to run. discard_first_run: Discard the first run of this page. This is usually used with page_repeat and pageset_repeat options. - is_action_name_to_run_optional: Determines what to do if - action_name_to_run is not empty but the page doesn't have that - action. The page will run (without any action) if - is_action_name_to_run_optional is True, otherwise the page - will fail. """ def __init__(self, action_name_to_run='', needs_browser_restart_after_each_page=False, discard_first_result=False, - clear_cache_before_each_run=False, - is_action_name_to_run_optional=False): + clear_cache_before_each_run=False): super(PageTest, self).__init__() self.options = None @@ -74,7 +68,6 @@ self._discard_first_result = discard_first_result self._clear_cache_before_each_run = clear_cache_before_each_run self._close_tabs_before_run = True - self._is_action_name_to_run_optional = is_action_name_to_run_optional @property def is_multi_tab_test(self): @@ -156,7 +149,7 @@ def CanRunForPage(self, page): # pylint: disable=W0613 """Override to customize if the test can be ran for the given page.""" - if self._action_name_to_run and not self._is_action_name_to_run_optional: + if self._action_name_to_run: return hasattr(page, self._action_name_to_run) return True
diff --git a/tools/telemetry/telemetry/results/chart_json_output_formatter.py b/tools/telemetry/telemetry/results/chart_json_output_formatter.py index 5229a5b..43af846 100644 --- a/tools/telemetry/telemetry/results/chart_json_output_formatter.py +++ b/tools/telemetry/telemetry/results/chart_json_output_formatter.py
@@ -54,6 +54,7 @@ 'format_version': '0.1', 'benchmark_name': benchmark_metadata.name, 'benchmark_description': benchmark_metadata.description, + 'benchmark_rerun_options': benchmark_metadata.rerun_options, 'charts': charts, }
diff --git a/tools/telemetry/telemetry/user_story/android/shared_app_state.py b/tools/telemetry/telemetry/user_story/android/shared_app_state.py index 8c16425..76177bd 100644 --- a/tools/telemetry/telemetry/user_story/android/shared_app_state.py +++ b/tools/telemetry/telemetry/user_story/android/shared_app_state.py
@@ -37,7 +37,7 @@ self._android_app = None self._current_user_story = None self._android_platform = platform.GetPlatformForDevice( - android_device.GetDevice(finder_options)) + android_device.GetDevice(finder_options), finder_options) assert self._android_platform, 'Unable to create android platform.' assert isinstance( self._android_platform, android_platform.AndroidPlatform)
diff --git a/tools/telemetry/telemetry/user_story/user_story_runner.py b/tools/telemetry/telemetry/user_story/user_story_runner.py index 695c114..ad9dde0b 100644 --- a/tools/telemetry/telemetry/user_story/user_story_runner.py +++ b/tools/telemetry/telemetry/user_story/user_story_runner.py
@@ -16,7 +16,6 @@ from telemetry.core import wpr_modes from telemetry.page import page_set as page_set_module from telemetry.page import page_test -from telemetry.page import shared_page_state from telemetry.page.actions import page_action from telemetry.results import results_options from telemetry.user_story import user_story_filter @@ -26,6 +25,10 @@ from telemetry.value import skip +class ArchiveError(Exception): + pass + + def AddCommandLineArgs(parser): user_story_filter.UserStoryFilter.AddCommandLineArgs(parser) results_options.AddResultsOptions(parser) @@ -104,6 +107,11 @@ except page_action.PageActionNotSupported as e: results.AddValue( skip.SkipValue(user_story, 'Unsupported page action: %s' % e)) + except Exception: + results.AddValue( + failure.FailureValue( + user_story, sys.exc_info(), 'Unhandlable exception raised.')) + raise else: if expectation == 'fail': logging.warning( @@ -324,13 +332,13 @@ '--use-live-sites.\nTo create an archive file add an ' 'archive_data_file property to the user story set and then ' 'run record_wpr.') - return False + raise ArchiveError('No archive data file.') if not wpr_archive_info: logging.error('The archive info file is missing.\n' 'To fix this, either add svn-internal to your ' '.gclient using http://goto/read-src-internal, ' 'or create a new archive using record_wpr.') - return False + raise ArchiveError('No archive info file.') wpr_archive_info.DownloadArchivesIfNeeded() # Report any problems with individual user story. @@ -366,7 +374,7 @@ ', '.join(user_story.display_name for user_story in user_stories_missing_archive_data)) if user_stories_missing_archive_path or user_stories_missing_archive_data: - return False + raise ArchiveError('Archive file is missing user stories.') # Only run valid user stories if no problems with the user story set or # individual user stories. return True
diff --git a/tools/telemetry/telemetry/user_story/user_story_runner_unittest.py b/tools/telemetry/telemetry/user_story/user_story_runner_unittest.py index 5429135..eed754f 100644 --- a/tools/telemetry/telemetry/user_story/user_story_runner_unittest.py +++ b/tools/telemetry/telemetry/user_story/user_story_runner_unittest.py
@@ -105,7 +105,7 @@ def _GetOptionForUnittest(): options = options_for_unittests.GetCopy() options.output_formats = ['none'] - options.suppress_gtest_report = True + options.suppress_gtest_report = False parser = options.CreateParser() user_story_runner.AddCommandLineArgs(parser) options.MergeDefaultValues(parser.get_default_values()) @@ -127,6 +127,9 @@ class UserStoryRunnerTest(unittest.TestCase): def setUp(self): + self.fake_stdout = StringIO.StringIO() + self.actual_stdout = sys.stdout + sys.stdout = self.fake_stdout self.options = _GetOptionForUnittest() self.expectations = test_expectations.TestExpectations() self.results = results_options.CreateResults( @@ -146,6 +149,7 @@ self._user_story_runner_logging_stub = None def tearDown(self): + sys.stdout = self.actual_stdout self.RestoreExceptionFormatter() def testGetUserStoryGroupsWithSameSharedUserStoryClass(self): @@ -237,21 +241,24 @@ us = user_story_set.UserStorySet() class SharedUserStoryThatCausesAppCrash(TestSharedPageState): def WillRunUserStory(self, user_storyz): - raise exceptions.AppCrashException() + raise exceptions.AppCrashException('App Foo crashes') us.AddUserStory(DummyLocalUserStory(SharedUserStoryThatCausesAppCrash)) user_story_runner.Run( DummyTest(), us, self.expectations, self.options, self.results) self.assertEquals(1, len(self.results.failures)) self.assertEquals(0, GetNumberOfSuccessfulPageRuns(self.results)) + self.assertIn('App Foo crashes', self.fake_stdout.getvalue()) def testUnknownExceptionIsFatal(self): self.SuppressExceptionFormatting() - us = user_story_set.UserStorySet() + uss = user_story_set.UserStorySet() class UnknownException(Exception): pass + # This erroneous test is set up to raise exception for the 2nd user story + # run. class Test(page_test.PageTest): def __init__(self, *args): super(Test, self).__init__(*args) @@ -260,18 +267,23 @@ def RunPage(self, *_): old_run_count = self.run_count self.run_count += 1 - if old_run_count == 0: - raise UnknownException + if old_run_count == 1: + raise UnknownException('FooBarzException') def ValidateAndMeasurePage(self, page, tab, results): pass - us.AddUserStory(DummyLocalUserStory(TestSharedPageState)) - us.AddUserStory(DummyLocalUserStory(TestSharedPageState)) + us1 = DummyLocalUserStory(TestSharedPageState) + us2 = DummyLocalUserStory(TestSharedPageState) + uss.AddUserStory(us1) + uss.AddUserStory(us2) test = Test() with self.assertRaises(UnknownException): user_story_runner.Run( - test, us, self.expectations, self.options, self.results) + test, uss, self.expectations, self.options, self.results) + self.assertEqual(set([us2]), self.results.pages_that_failed) + self.assertEqual(set([us1]), self.results.pages_that_succeeded) + self.assertIn('FooBarzException', self.fake_stdout.getvalue()) def testRaiseBrowserGoneExceptionFromRunPage(self): self.SuppressExceptionFormatting() @@ -415,39 +427,37 @@ self.options.page_repeat = 1 self.options.pageset_repeat = 2 self.options.output_formats = ['buildbot'] - output = StringIO.StringIO() - real_stdout = sys.stdout - sys.stdout = output - try: - results = results_options.CreateResults( - EmptyMetadataForTest(), self.options) - user_story_runner.Run( - Measurement(), us, self.expectations, self.options, results) - results.PrintSummary() - contents = output.getvalue() - self.assertEquals(4, GetNumberOfSuccessfulPageRuns(results)) - self.assertEquals(0, len(results.failures)) - self.assertIn('RESULT metric: blank= [1,3] unit', contents) - self.assertIn('RESULT metric: green= [2,4] unit', contents) - self.assertIn('*RESULT metric: metric= [1,2,3,4] unit', contents) - finally: - sys.stdout = real_stdout + results = results_options.CreateResults( + EmptyMetadataForTest(), self.options) + user_story_runner.Run( + Measurement(), us, self.expectations, self.options, results) + results.PrintSummary() + contents = self.fake_stdout.getvalue() + self.assertEquals(4, GetNumberOfSuccessfulPageRuns(results)) + self.assertEquals(0, len(results.failures)) + self.assertIn('RESULT metric: blank= [1,3] unit', contents) + self.assertIn('RESULT metric: green= [2,4] unit', contents) + self.assertIn('*RESULT metric: metric= [1,2,3,4] unit', contents) def testUpdateAndCheckArchives(self): uss = user_story_set.UserStorySet() uss.AddUserStory(page_module.Page( 'http://www.testurl.com', uss, uss.base_dir)) # Page set missing archive_data_file. - self.assertFalse(user_story_runner._UpdateAndCheckArchives( - uss.archive_data_file, uss.wpr_archive_info, uss.user_stories)) + self.assertRaises( + user_story_runner.ArchiveError, + user_story_runner._UpdateAndCheckArchives, + uss.archive_data_file, uss.wpr_archive_info, uss.user_stories) uss = user_story_set.UserStorySet( archive_data_file='missing_archive_data_file.json') uss.AddUserStory(page_module.Page( 'http://www.testurl.com', uss, uss.base_dir)) # Page set missing json file specified in archive_data_file. - self.assertFalse(user_story_runner._UpdateAndCheckArchives( - uss.archive_data_file, uss.wpr_archive_info, uss.user_stories)) + self.assertRaises( + user_story_runner.ArchiveError, + user_story_runner._UpdateAndCheckArchives, + uss.archive_data_file, uss.wpr_archive_info, uss.user_stories) uss = user_story_set.UserStorySet( archive_data_file='../../unittest_data/archive_files/test.json', @@ -460,8 +470,10 @@ uss.AddUserStory(page_module.Page( 'http://www.google.com', uss, uss.base_dir)) # Page set with an archive_data_file which exists but is missing a page. - self.assertFalse(user_story_runner._UpdateAndCheckArchives( - uss.archive_data_file, uss.wpr_archive_info, uss.user_stories)) + self.assertRaises( + user_story_runner.ArchiveError, + user_story_runner._UpdateAndCheckArchives, + uss.archive_data_file, uss.wpr_archive_info, uss.user_stories) uss = user_story_set.UserStorySet( archive_data_file='../../unittest_data/test_missing_wpr_file.json', @@ -472,8 +484,10 @@ 'http://www.google.com', uss, uss.base_dir)) # Page set with an archive_data_file which exists and contains all pages # but fails to find a wpr file. - self.assertFalse(user_story_runner._UpdateAndCheckArchives( - uss.archive_data_file, uss.wpr_archive_info, uss.user_stories)) + self.assertRaises( + user_story_runner.ArchiveError, + user_story_runner._UpdateAndCheckArchives, + uss.archive_data_file, uss.wpr_archive_info, uss.user_stories) def _testMaxFailuresOptionIsRespectedAndOverridable(
diff --git a/tools/telemetry/telemetry/util/external_modules.py b/tools/telemetry/telemetry/util/external_modules.py index 6a504ae..92faf59 100644 --- a/tools/telemetry/telemetry/util/external_modules.py +++ b/tools/telemetry/telemetry/util/external_modules.py
@@ -9,6 +9,7 @@ MODULES = { 'cv2': (version.StrictVersion('2.4.8'), version.StrictVersion('3.0.0')), 'numpy': (version.StrictVersion('1.6.1'), None), + 'psutil': (version.StrictVersion('0.5.0'), None), } def ImportRequiredModule(module):
diff --git a/tools/telemetry/telemetry/web_perf/timeline_based_measurement.py b/tools/telemetry/telemetry/web_perf/timeline_based_measurement.py index 03a90ad..b41d2b65 100644 --- a/tools/telemetry/telemetry/web_perf/timeline_based_measurement.py +++ b/tools/telemetry/telemetry/web_perf/timeline_based_measurement.py
@@ -139,6 +139,10 @@ The v8 overhead level is a temporary solution that may be removed. """ self._overhead_level = overhead_level + self._category_filters = [] + + def ExtendTraceCategoryFilters(self, filters): + self._category_filters.extend(filters) class TimelineBasedMeasurement(object): @@ -165,6 +169,7 @@ """ def __init__(self, options): self._overhead_level = options._overhead_level + self._category_filters = options._category_filters def WillRunUserStory(self, tracing_controller, synthetic_delay_categories=None): @@ -192,6 +197,9 @@ else: category_filter = tracing_category_filter.CreateDebugOverheadFilter() + for new_category_filter in self._category_filters: + category_filter.AddIncludedCategory(new_category_filter) + # TODO(slamm): Move synthetic_delay_categories to the TBM options. for delay in synthetic_delay_categories or []: category_filter.AddSyntheticDelay(delay)
diff --git a/tools/valgrind/drmemory/suppressions_full.txt b/tools/valgrind/drmemory/suppressions_full.txt index a0da41c..144e5b57559 100644 --- a/tools/valgrind/drmemory/suppressions_full.txt +++ b/tools/valgrind/drmemory/suppressions_full.txt
@@ -1889,3 +1889,7 @@ *!ash::test::ShelfViewTest_OverflowBubbleSize_Test::TestBody *!testing::internal::HandleExceptionsInMethodIfSupported<> +UNINITIALIZED READ +name=bug_446256 +*!`anonymous namespace'::GraphicsContextTest_trackDisplayListRecording_Test::TestBody +*!testing::internal::HandleExceptionsInMethodIfSupported<>
diff --git a/tools/valgrind/gtest_exclude/base_unittests.gtest_win32.txt b/tools/valgrind/gtest_exclude/base_unittests.gtest_win32.txt index 840a303..dca1b42 100644 --- a/tools/valgrind/gtest_exclude/base_unittests.gtest_win32.txt +++ b/tools/valgrind/gtest_exclude/base_unittests.gtest_win32.txt
@@ -3,7 +3,6 @@ # Very sensitive to slowdown TimeTicks.Deltas -TimeTicks.HighResNow TimerTest.RepeatingTimer* # This Windows-native sampling profiler test does not work under our tools
diff --git a/tools/valgrind/gtest_exclude/browser_tests.gtest-drmemory.txt b/tools/valgrind/gtest_exclude/browser_tests.gtest-drmemory.txt index 288d6cd..faf853d 100644 --- a/tools/valgrind/gtest_exclude/browser_tests.gtest-drmemory.txt +++ b/tools/valgrind/gtest_exclude/browser_tests.gtest-drmemory.txt
@@ -19,3 +19,10 @@ # http://crbug.com/403007 WorkerDevToolsSanityTest.InspectSharedWorker + +# http://crbug.com/451991 +AppViewTest.TestAppViewMultipleConnects +BrowserViewTest.DevToolsUpdatesBrowserWindow + +# http://crbug.com/451992 +ExtensionLoadingTest.UpgradeAfterNavigatingFromOverriddenNewTabPage
diff --git a/tools/valgrind/gtest_exclude/cc_unittests.gtest-drmemory.txt b/tools/valgrind/gtest_exclude/cc_unittests.gtest-drmemory.txt new file mode 100644 index 0000000..8fd7cbd --- /dev/null +++ b/tools/valgrind/gtest_exclude/cc_unittests.gtest-drmemory.txt
@@ -0,0 +1,2 @@ +# http://crbug.com/451988 +LayerTreeHostPictureTestTwinLayer.RunSingleThread_DirectRenderer_ImplSidePaint
diff --git a/tools/valgrind/gtest_exclude/content_browsertests.gtest-drmemory.txt b/tools/valgrind/gtest_exclude/content_browsertests.gtest-drmemory.txt index 6ef00d8..0942883 100644 --- a/tools/valgrind/gtest_exclude/content_browsertests.gtest-drmemory.txt +++ b/tools/valgrind/gtest_exclude/content_browsertests.gtest-drmemory.txt
@@ -20,3 +20,8 @@ ServiceWorkerVersionBrowserTest.Activate_NoEventListener ServiceWorkerBrowserTest.ImportsBustMemcache +# http://crbug.com/293125 +WebRtcBrowserTest.CanMakeEmptyCallThenAddStreamsAndRenegotiate + +# http://crbug.com/451983 +DumpAccessibilityEventsTest.AccessibilityEventsTextChanged
diff --git a/tools/valgrind/gtest_exclude/content_unittests.gtest_linux.txt b/tools/valgrind/gtest_exclude/content_unittests.gtest_linux.txt new file mode 100644 index 0000000..bd9d1388 --- /dev/null +++ b/tools/valgrind/gtest_exclude/content_unittests.gtest_linux.txt
@@ -0,0 +1,2 @@ +# http://crbug.com/452077 +ServiceWorkerCacheStorageManagerTests/ServiceWorkerCacheStorageManagerTestP.StorageMatchAllCacheNotReferenced/1
diff --git a/tools/valgrind/gtest_exclude/net_unittests.gtest_linux.txt b/tools/valgrind/gtest_exclude/net_unittests.gtest_linux.txt index a93d588..d8dad715 100644 --- a/tools/valgrind/gtest_exclude/net_unittests.gtest_linux.txt +++ b/tools/valgrind/gtest_exclude/net_unittests.gtest_linux.txt
@@ -3,3 +3,5 @@ DiskCacheEntryTest.SimpleCacheGrowData DiskCacheEntryTest.SimpleCacheSizeChanges +# Flaky. crbug.com/451999 +WebSocketEndpointLockManagerTest.UnlockEndpointIsDelayed
diff --git a/tools/valgrind/gtest_exclude/net_unittests.gtest_mac.txt b/tools/valgrind/gtest_exclude/net_unittests.gtest_mac.txt index 6986bdf..df0a0935 100644 --- a/tools/valgrind/gtest_exclude/net_unittests.gtest_mac.txt +++ b/tools/valgrind/gtest_exclude/net_unittests.gtest_mac.txt
@@ -4,3 +4,6 @@ # These tests fail under Valgrind on Mac, see http://crbug.com/62314 SSLClientSocketTest.* HTTPSRequestTest.* + +# Flaky. crbug.com/451999 +WebSocketEndpointLockManagerTest.UnlockEndpointIsDelayed
diff --git a/tools/valgrind/gtest_exclude/unit_tests.gtest_linux.txt b/tools/valgrind/gtest_exclude/unit_tests.gtest_linux.txt index a43a673..5a8f1bc 100644 --- a/tools/valgrind/gtest_exclude/unit_tests.gtest_linux.txt +++ b/tools/valgrind/gtest_exclude/unit_tests.gtest_linux.txt
@@ -32,3 +32,6 @@ # http://crbug.com/403533 ExtensionPathUtilTest.BasicPrettifyPathTest + +# http://crbug.com/452071 +SupervisedUserServiceExtensionTest.InstallContentPacks
diff --git a/tools/valgrind/memcheck/suppressions.txt b/tools/valgrind/memcheck/suppressions.txt index 9ce34df..e73272c 100644 --- a/tools/valgrind/memcheck/suppressions.txt +++ b/tools/valgrind/memcheck/suppressions.txt
@@ -1767,17 +1767,6 @@ fun:_ZN4base5files12_GLOBAL__N_121InotifyReaderCallbackEPNS1_13InotifyReaderEii } { - bug_146464 - Memcheck:Leak - fun:realloc - fun:add_codeset.isra.10 - ... - fun:XCreatePixmap - fun:XCreateBitmapFromData - ... - fun:_ZN4aura19RootWindowHostLinuxC1EPNS_22RootWindowHostDelegateERKN3gfx4RectE -} -{ bug_146950 Memcheck:Leak fun:malloc
diff --git a/tools/valgrind/memcheck/suppressions_linux.txt b/tools/valgrind/memcheck/suppressions_linux.txt index 0e75ee1..6d031be 100644 --- a/tools/valgrind/memcheck/suppressions_linux.txt +++ b/tools/valgrind/memcheck/suppressions_linux.txt
@@ -52,3 +52,18 @@ fun:_ZN3IPC11ChannelMojo17InitMessageReaderEN4mojo16ScopedHandleBaseINS1_17MessagePipeHandleEEEi fun:_ZN3IPC12_GLOBAL__N_117ServerChannelMojo27ClientChannelWasInitializedEi } +{ + bug_452002 + Memcheck:Leak + fun:_Znw* + fun:_ZN11leveldb_env11ChromiumEnv11StartThreadEPFvPvES1_ + fun:_ZN11leveldb_env11ChromiumEnv8ScheduleEPFvPvES1_ + fun:_ZN7leveldb6DBImpl23MaybeScheduleCompactionEv + fun:_ZN7leveldb6DBImpl16MakeRoomForWriteEb + fun:_ZN7leveldb6DBImpl5WriteERKNS_12WriteOptionsEPNS_10WriteBatchE + fun:_ZN17LeveldbValueStore9WriteToDbEPN7leveldb10WriteBatchE + fun:_ZN17LeveldbValueStore3SetEiRKSsRKN4base5ValueE + fun:_ZN10extensions28SettingsStorageQuotaEnforcer3SetEiRKSsRKN4base5ValueE + fun:_ZN10extensions28WeakUnlimitedSettingsStorage3SetEiRKSsRKN4base5ValueE + fun:_ZN10extensions12_GLOBAL__N_1L33UnlimitedLocalStorageTestCallbackEP10ValueStore +}
diff --git a/tools/vim/chromium.ycm_extra_conf.py b/tools/vim/chromium.ycm_extra_conf.py index 2901c54..76fce67 100644 --- a/tools/vim/chromium.ycm_extra_conf.py +++ b/tools/vim/chromium.ycm_extra_conf.py
@@ -56,7 +56,7 @@ with open(os.devnull, 'rb') as DEVNULL: output = subprocess.check_output(['clang', '-v', '-E', '-x', 'c++', '-'], stdin=DEVNULL, stderr=subprocess.STDOUT) - except (FileNotFoundError, subprocess.CalledProcessError): + except: return [] includes_regex = r'#include <\.\.\.> search starts here:\s*' \ r'(.*?)End of search list\.'
diff --git a/tools/vim/ninja_output.py b/tools/vim/ninja_output.py index f6d41d5..e343c5b 100644 --- a/tools/vim/ninja_output.py +++ b/tools/vim/ninja_output.py
@@ -5,40 +5,53 @@ import os import os.path +import re def GetNinjaOutputDirectory(chrome_root, configuration=None): """Returns <chrome_root>/<output_dir>/(Release|Debug). + The output_dir is detected in the following ways, in order of precedence: + 1. CHROMIUM_OUT_DIR environment variable. + 2. GYP_GENERATOR_FLAGS environment variable output_dir property. + 3. Symlink target, if src/out is a symlink. + 4. Most recently modified (e.g. built) directory called out or out_*. + The configuration chosen is the one most recently generated/built, but can be - overriden via the <configuration> parameter. Detects a custom output_dir - specified by GYP_GENERATOR_FLAGS.""" + overriden via the <configuration> parameter.""" - output_dir = 'out' - generator_flags = os.getenv('GYP_GENERATOR_FLAGS', '').split(' ') - for flag in generator_flags: - name_value = flag.split('=', 1) - if len(name_value) == 2 and name_value[0] == 'output_dir': - output_dir = name_value[1] + output_dirs = [] + if ('CHROMIUM_OUT_DIR' in os.environ and + os.path.isdir(os.path.join(chrome_root, os.environ['CHROMIUM_OUT_DIR']))): + output_dirs = [os.environ['CHROMIUM_OUT_DIR']] + if not output_dirs: + generator_flags = os.getenv('GYP_GENERATOR_FLAGS', '').split(' ') + for flag in generator_flags: + name_value = flag.split('=', 1) + if (len(name_value) == 2 and name_value[0] == 'output_dir' and + os.path.isdir(os.path.join(chrome_root, name_value[1]))): + output_dirs = [name_value[1]] + if not output_dirs: + out = os.path.join(chrome_root, 'out') + if os.path.islink(out): + out_target = os.path.join(os.path.dirname(out), os.readlink(out)) + if os.path.exists(out_target): + output_dirs = [out_target] + if not output_dirs: + for f in os.listdir(chrome_root): + if (re.match('out(?:$|_)', f) and + os.path.isdir(os.path.join(chrome_root, f))): + output_dirs.append(f) - root = os.path.join(chrome_root, output_dir) - if configuration: - return os.path.join(root, configuration) + configs = [configuration] if configuration else ['Debug', 'Release'] + output_paths = [os.path.join(chrome_root, out_dir, config) + for out_dir in output_dirs for config in configs] - debug_path = os.path.join(root, 'Debug') - release_path = os.path.join(root, 'Release') + def approx_directory_mtime(path): + if not os.path.exists(path): + return -1 + # This is a heuristic; don't recurse into subdirectories. + paths = [path] + [os.path.join(path, f) for f in os.listdir(path)] + return max(os.path.getmtime(p) for p in paths) - def is_release_15s_newer(test_path): - try: - debug_mtime = os.path.getmtime(os.path.join(debug_path, test_path)) - except os.error: - debug_mtime = 0 - try: - rel_mtime = os.path.getmtime(os.path.join(release_path, test_path)) - except os.error: - rel_mtime = 0 - return rel_mtime - debug_mtime >= 15 - - if is_release_15s_newer('build.ninja') or is_release_15s_newer('protoc'): - return release_path - return debug_path + return max(output_paths, key=approx_directory_mtime)
diff --git a/ui/accessibility/ax_tree.cc b/ui/accessibility/ax_tree.cc index ecfbae8..bb67a47 100644 --- a/ui/accessibility/ax_tree.cc +++ b/ui/accessibility/ax_tree.cc
@@ -88,11 +88,11 @@ return false; } if (node == root_) { - DestroyNodeAndSubtree(root_); + DestroySubtree(root_); root_ = NULL; } else { for (int i = 0; i < node->child_count(); ++i) - DestroyNodeAndSubtree(node->ChildAtIndex(i)); + DestroySubtree(node->ChildAtIndex(i)); std::vector<AXNode*> children; node->SwapChildren(children); update_state.pending_nodes.insert(node); @@ -114,17 +114,25 @@ } if (delegate_) { + std::set<AXNode*>& new_nodes = update_state.new_nodes; + std::vector<AXTreeDelegate::Change> changes; + changes.reserve(update.nodes.size()); for (size_t i = 0; i < update.nodes.size(); ++i) { AXNode* node = GetFromId(update.nodes[i].id); - if (update_state.new_nodes.find(node) != update_state.new_nodes.end()) { - delegate_->OnNodeCreationFinished(node); - update_state.new_nodes.erase(node); + if (new_nodes.find(node) != new_nodes.end()) { + if (new_nodes.find(node->parent()) == new_nodes.end()) { + changes.push_back( + AXTreeDelegate::Change(node, AXTreeDelegate::SUBTREE_CREATED)); + } else { + changes.push_back( + AXTreeDelegate::Change(node, AXTreeDelegate::NODE_CREATED)); + } } else { - delegate_->OnNodeChangeFinished(node); + changes.push_back( + AXTreeDelegate::Change(node, AXTreeDelegate::NODE_CHANGED)); } } - if (root_->id() != old_root_id) - delegate_->OnRootChanged(root_); + delegate_->OnAtomicUpdateFinished(root_->id() != old_root_id, changes); } return true; @@ -176,7 +184,7 @@ // anymore. if (!DeleteOldChildren(node, src.child_ids)) { if (new_root) - DestroyNodeAndSubtree(new_root); + DestroySubtree(new_root); return false; } @@ -191,13 +199,19 @@ if (src.role == AX_ROLE_ROOT_WEB_AREA && (!root_ || root_->id() != src.id)) { if (root_) - DestroyNodeAndSubtree(root_); + DestroySubtree(root_); root_ = node; } return success; } +void AXTree::DestroySubtree(AXNode* node) { + if (delegate_) + delegate_->OnSubtreeWillBeDeleted(node); + DestroyNodeAndSubtree(node); +} + void AXTree::DestroyNodeAndSubtree(AXNode* node) { id_map_.erase(node->id()); for (int i = 0; i < node->child_count(); ++i) @@ -226,7 +240,7 @@ for (size_t i = 0; i < old_children.size(); ++i) { int old_id = old_children[i]->id(); if (new_child_id_set.find(old_id) == new_child_id_set.end()) - DestroyNodeAndSubtree(old_children[i]); + DestroySubtree(old_children[i]); } return true;
diff --git a/ui/accessibility/ax_tree.h b/ui/accessibility/ax_tree.h index b4baac4..c8470c0 100644 --- a/ui/accessibility/ax_tree.h +++ b/ui/accessibility/ax_tree.h
@@ -22,15 +22,15 @@ // Be careful, as the tree may be in an inconsistent state at this time; // don't walk the parents and children at this time: // OnNodeWillBeDeleted +// OnSubtreeWillBeDeleted // OnNodeCreated // OnNodeChanged // -// Other notifications are called at the end of an atomic update operation. -// From these, it's safe to walk the tree and do any initialization that -// assumes the tree is in a consistent state. -// OnNodeCreationFinished -// OnNodeChangeFinished -// OnRootChanged +// In addition, one additional notification is fired at the end of an +// atomic update, and it provides a vector of nodes that were added or +// changed, for final postprocessing: +// OnAtomicUpdateFinished +// class AX_EXPORT AXTreeDelegate { public: AXTreeDelegate(); @@ -41,6 +41,11 @@ // in the middle of an update, the tree may be in an invalid state! virtual void OnNodeWillBeDeleted(AXNode* node) = 0; + // Same as OnNodeWillBeDeleted, but only called once for an entire subtree. + // This is called in the middle of an update, the tree may be in an + // invalid state! + virtual void OnSubtreeWillBeDeleted(AXNode* node) = 0; + // Called immediately after a new node is created. The tree may be in // the middle of an update, don't walk the parents and children now. virtual void OnNodeCreated(AXNode* node) = 0; @@ -49,16 +54,28 @@ // the middle of an update, don't walk the parents and children now. virtual void OnNodeChanged(AXNode* node) = 0; - // Called for each new node at the end of an update operation, - // when the tree is in a consistent state. - virtual void OnNodeCreationFinished(AXNode* node) = 0; + enum ChangeType { + NODE_CREATED, + SUBTREE_CREATED, + NODE_CHANGED + }; - // Called for each existing node that changed at the end of an update - // operation, when the tree is in a consistent state. - virtual void OnNodeChangeFinished(AXNode* node) = 0; + struct Change { + Change(AXNode* node, ChangeType type) { + this->node = node; + this->type = type; + } + AXNode *node; + ChangeType type; + }; - // Called at the end of an update operation when the root node changes. - virtual void OnRootChanged(AXNode* new_root) = 0; + // Called at the end of the update operation. Every node that was added + // or changed will be included in |changes|, along with an enum indicating + // the type of change - either (1) a node was created, (2) a node was created + // and it's the root of a new subtree, or (3) a node was changed. Finally, + // a bool indicates if the root of the tree was changed or not. + virtual void OnAtomicUpdateFinished(bool root_changed, + const std::vector<Change>& changes) = 0; }; // AXTree is a live, managed tree of AXNode objects that can receive @@ -97,6 +114,10 @@ void OnRootChanged(); + // Notify the delegate that the subtree rooted at |node| will be destroyed, + // then call DestroyNodeAndSubtree on it. + void DestroySubtree(AXNode* node); + // Call Destroy() on |node|, and delete it from the id map, and then // call recursively on all nodes in its subtree. void DestroyNodeAndSubtree(AXNode* node);
diff --git a/ui/accessibility/ax_tree_unittest.cc b/ui/accessibility/ax_tree_unittest.cc index 6c5d885..8be0f3901 100644 --- a/ui/accessibility/ax_tree_unittest.cc +++ b/ui/accessibility/ax_tree_unittest.cc
@@ -16,10 +16,16 @@ class FakeAXTreeDelegate : public AXTreeDelegate { public: + FakeAXTreeDelegate() : root_changed_(false) {} + void OnNodeWillBeDeleted(AXNode* node) override { deleted_ids_.push_back(node->id()); } + void OnSubtreeWillBeDeleted(AXNode* node) override { + subtree_deleted_ids_.push_back(node->id()); + } + void OnNodeCreated(AXNode* node) override { created_ids_.push_back(node->id()); } @@ -28,32 +34,51 @@ changed_ids_.push_back(node->id()); } - void OnNodeCreationFinished(AXNode* node) override { - creation_finished_ids_.push_back(node->id()); + void OnAtomicUpdateFinished(bool root_changed, + const std::vector<Change>& changes) override { + root_changed_ = root_changed; + + for (size_t i = 0; i < changes.size(); ++i) { + int id = changes[i].node->id(); + switch (changes[i].type) { + case NODE_CREATED: + node_creation_finished_ids_.push_back(id); + break; + case SUBTREE_CREATED: + subtree_creation_finished_ids_.push_back(id); + break; + case NODE_CHANGED: + change_finished_ids_.push_back(id); + break; + } + } } - void OnNodeChangeFinished(AXNode* node) override { - change_finished_ids_.push_back(node->id()); - } - - void OnRootChanged(AXNode* new_root) override { - new_root_ids_.push_back(new_root->id()); - } - + bool root_changed() const { return root_changed_; } const std::vector<int32>& deleted_ids() { return deleted_ids_; } - const std::vector<int32>& created_ids() { return created_ids_; } - const std::vector<int32>& creation_finished_ids() { - return creation_finished_ids_; + const std::vector<int32>& subtree_deleted_ids() { + return subtree_deleted_ids_; } - const std::vector<int32>& new_root_ids() { return new_root_ids_; } + const std::vector<int32>& created_ids() { return created_ids_; } + const std::vector<int32>& node_creation_finished_ids() { + return node_creation_finished_ids_; + } + const std::vector<int32>& subtree_creation_finished_ids() { + return subtree_creation_finished_ids_; + } + const std::vector<int32>& change_finished_ids() { + return change_finished_ids_; + } private: + bool root_changed_; std::vector<int32> deleted_ids_; + std::vector<int32> subtree_deleted_ids_; std::vector<int32> created_ids_; - std::vector<int32> creation_finished_ids_; std::vector<int32> changed_ids_; + std::vector<int32> node_creation_finished_ids_; + std::vector<int32> subtree_creation_finished_ids_; std::vector<int32> change_finished_ids_; - std::vector<int32> new_root_ids_; }; } // namespace @@ -260,37 +285,44 @@ TEST(AXTreeTest, TreeDelegateIsCalled) { AXTreeUpdate initial_state; - initial_state.nodes.resize(1); + initial_state.nodes.resize(2); initial_state.nodes[0].id = 1; initial_state.nodes[0].role = AX_ROLE_ROOT_WEB_AREA; + initial_state.nodes[0].child_ids.push_back(2); + initial_state.nodes[1].id = 2; AXTree tree(initial_state); AXTreeUpdate update; update.node_id_to_clear = 1; update.nodes.resize(2); - update.nodes[0].id = 2; + update.nodes[0].id = 3; update.nodes[0].role = AX_ROLE_ROOT_WEB_AREA; - update.nodes[0].child_ids.push_back(3); - update.nodes[1].id = 3; + update.nodes[0].child_ids.push_back(4); + update.nodes[1].id = 4; FakeAXTreeDelegate fake_delegate; tree.SetDelegate(&fake_delegate); EXPECT_TRUE(tree.Unserialize(update)); - ASSERT_EQ(1U, fake_delegate.deleted_ids().size()); - EXPECT_EQ(1, fake_delegate.deleted_ids()[0]); + ASSERT_EQ(2U, fake_delegate.deleted_ids().size()); + EXPECT_EQ(2, fake_delegate.deleted_ids()[0]); + EXPECT_EQ(1, fake_delegate.deleted_ids()[1]); + + ASSERT_EQ(1U, fake_delegate.subtree_deleted_ids().size()); + EXPECT_EQ(1, fake_delegate.subtree_deleted_ids()[0]); ASSERT_EQ(2U, fake_delegate.created_ids().size()); - EXPECT_EQ(2, fake_delegate.created_ids()[0]); - EXPECT_EQ(3, fake_delegate.created_ids()[1]); + EXPECT_EQ(3, fake_delegate.created_ids()[0]); + EXPECT_EQ(4, fake_delegate.created_ids()[1]); - ASSERT_EQ(2U, fake_delegate.creation_finished_ids().size()); - EXPECT_EQ(2, fake_delegate.creation_finished_ids()[0]); - EXPECT_EQ(3, fake_delegate.creation_finished_ids()[1]); + ASSERT_EQ(1U, fake_delegate.subtree_creation_finished_ids().size()); + EXPECT_EQ(3, fake_delegate.subtree_creation_finished_ids()[0]); - ASSERT_EQ(1U, fake_delegate.new_root_ids().size()); - EXPECT_EQ(2, fake_delegate.new_root_ids()[0]); + ASSERT_EQ(1U, fake_delegate.node_creation_finished_ids().size()); + EXPECT_EQ(4, fake_delegate.node_creation_finished_ids()[0]); + + ASSERT_EQ(true, fake_delegate.root_changed()); tree.SetDelegate(NULL); }
diff --git a/ui/app_list/app_list_switches.cc b/ui/app_list/app_list_switches.cc index a8c4c299..a80013f2 100644 --- a/ui/app_list/app_list_switches.cc +++ b/ui/app_list/app_list_switches.cc
@@ -13,9 +13,6 @@ // added to the experimental app launcher. const char kCustomLauncherPage[] = "custom-launcher-page"; -// If set, the app info context menu item is not available in the app list UI. -const char kDisableAppInfo[] = "disable-app-list-app-info"; - // If set, the app list will not be dismissed when it loses focus. This is // useful when testing the app list or a custom launcher page. It can still be // dismissed via the other methods (like the Esc key). @@ -72,10 +69,9 @@ bool IsAppInfoEnabled() { #if defined(OS_MACOSX) - if (!IsMacViewsAppListListEnabled()) - return false; + return IsMacViewsAppListListEnabled(); #endif - return !base::CommandLine::ForCurrentProcess()->HasSwitch(kDisableAppInfo); + return true; } bool IsExperimentalAppListEnabled() {
diff --git a/ui/app_list/app_list_switches.h b/ui/app_list/app_list_switches.h index e4ae150..7585f60f 100644 --- a/ui/app_list/app_list_switches.h +++ b/ui/app_list/app_list_switches.h
@@ -13,7 +13,6 @@ // Please keep these flags sorted. APP_LIST_EXPORT extern const char kCustomLauncherPage[]; -APP_LIST_EXPORT extern const char kDisableAppInfo[]; APP_LIST_EXPORT extern const char kDisableAppListDismissOnBlur[]; APP_LIST_EXPORT extern const char kDisableDriveAppsInAppList[]; APP_LIST_EXPORT extern const char kDisableSyncAppList[];
diff --git a/ui/app_list/search/dictionary_data_store.cc b/ui/app_list/search/dictionary_data_store.cc index 41ac884..b867be4 100644 --- a/ui/app_list/search/dictionary_data_store.cc +++ b/ui/app_list/search/dictionary_data_store.cc
@@ -71,12 +71,12 @@ base::DictionaryValue* dict_value = NULL; if (error_code != JSONFileValueSerializer::JSON_NO_ERROR || !value || !value->GetAsDictionary(&dict_value) || !dict_value) { - return scoped_ptr<base::DictionaryValue>(); + return nullptr; } base::DictionaryValue* return_dict = dict_value->DeepCopy(); cached_dict_.reset(dict_value); - return make_scoped_ptr(return_dict).Pass(); + return make_scoped_ptr(return_dict); } bool DictionaryDataStore::SerializeData(std::string* data) {
diff --git a/ui/app_list/search/history_data_store.cc b/ui/app_list/search/history_data_store.cc index 996adc4..5338220 100644 --- a/ui/app_list/search/history_data_store.cc +++ b/ui/app_list/search/history_data_store.cc
@@ -59,13 +59,13 @@ std::string version; if (!dict->GetStringWithoutPathExpansion(kKeyVersion, &version) || version != kCurrentVersion) { - return scoped_ptr<HistoryData::Associations>(); + return nullptr; } const base::DictionaryValue* assoc_dict = NULL; if (!dict->GetDictionaryWithoutPathExpansion(kKeyAssociations, &assoc_dict) || !assoc_dict) { - return scoped_ptr<HistoryData::Associations>(); + return nullptr; } scoped_ptr<HistoryData::Associations> data(new HistoryData::Associations); @@ -212,7 +212,7 @@ OnLoadedCallback callback, scoped_ptr<base::DictionaryValue> dict) { if (!dict) { - callback.Run(scoped_ptr<HistoryData::Associations>()); + callback.Run(nullptr); } else { callback.Run(Parse(dict.Pass()).Pass()); }
diff --git a/ui/app_list/test/test_search_result.cc b/ui/app_list/test/test_search_result.cc index 32e394c..558a630b 100644 --- a/ui/app_list/test/test_search_result.cc +++ b/ui/app_list/test/test_search_result.cc
@@ -18,7 +18,7 @@ scoped_ptr<SearchResult> TestSearchResult::Duplicate() { NOTREACHED(); - return scoped_ptr<SearchResult>(); + return nullptr; } } // namespace app_list
diff --git a/ui/aura/bench/bench_main.cc b/ui/aura/bench/bench_main.cc index 0ab5a736..e2cb23e 100644 --- a/ui/aura/bench/bench_main.cc +++ b/ui/aura/bench/bench_main.cc
@@ -94,6 +94,7 @@ frames_(0), max_frames_(max_frames) { } + virtual ~BenchCompositorObserver() {} void OnCompositingDidCommit(ui::Compositor* compositor) override {} @@ -123,6 +124,8 @@ void OnCompositingLockStateChanged(Compositor* compositor) override {} + void OnCompositingShuttingDown(ui::Compositor* compositor) override {} + virtual void Draw() {} int frames() const { return frames_; }
diff --git a/ui/aura/gestures/gesture_recognizer_unittest.cc b/ui/aura/gestures/gesture_recognizer_unittest.cc index fed5ea4..951aa44 100644 --- a/ui/aura/gestures/gesture_recognizer_unittest.cc +++ b/ui/aura/gestures/gesture_recognizer_unittest.cc
@@ -2554,7 +2554,7 @@ // there is at least one case where we need to allow a touch press // from a currently used touch id. See crbug.com/373125 for details. EXPECT_TRUE(delegate->begin()); - EXPECT_FALSE(delegate->tap_down()); + EXPECT_TRUE(delegate->tap_down()); EXPECT_TRUE(delegate->tap_cancel()); EXPECT_FALSE(delegate->scroll_begin()); }
diff --git a/ui/aura/test/aura_test_helper.cc b/ui/aura/test/aura_test_helper.cc index 3b02474..837f81e 100644 --- a/ui/aura/test/aura_test_helper.cc +++ b/ui/aura/test/aura_test_helper.cc
@@ -60,8 +60,7 @@ Env::GetInstance()->set_context_factory(context_factory); // Unit tests generally don't want to query the system, rather use the state // from RootWindow. - EnvTestHelper(Env::GetInstance()).SetInputStateLookup( - scoped_ptr<InputStateLookup>()); + EnvTestHelper(Env::GetInstance()).SetInputStateLookup(nullptr); ui::InitializeInputMethodForTesting();
diff --git a/ui/base/dragdrop/drag_drop_types.h b/ui/base/dragdrop/drag_drop_types.h index c74d4e2..6b25f13 100644 --- a/ui/base/dragdrop/drag_drop_types.h +++ b/ui/base/dragdrop/drag_drop_types.h
@@ -20,9 +20,10 @@ }; enum DragEventSource { - DRAG_EVENT_SOURCE_MOUSE, + DRAG_EVENT_SOURCE_MOUSE = 0, DRAG_EVENT_SOURCE_TOUCH, - DRAG_EVENT_SOURCE_LAST = DRAG_EVENT_SOURCE_TOUCH + DRAG_EVENT_SOURCE_LAST = DRAG_EVENT_SOURCE_TOUCH, + DRAG_EVENT_SOURCE_COUNT }; #if defined(OS_WIN)
diff --git a/ui/base/ime/chromeos/ime_keyboard_ozone.h b/ui/base/ime/chromeos/ime_keyboard_ozone.h index da2f8f54..f41d9a0 100644 --- a/ui/base/ime/chromeos/ime_keyboard_ozone.h +++ b/ui/base/ime/chromeos/ime_keyboard_ozone.h
@@ -22,18 +22,17 @@ class UI_BASE_EXPORT ImeKeyboardOzone : public ImeKeyboard { public: ImeKeyboardOzone(ui::InputController* controller); - virtual ~ImeKeyboardOzone(); + ~ImeKeyboardOzone() override; - virtual bool SetCurrentKeyboardLayoutByName(const std::string& layout_name) - override; - virtual bool SetAutoRepeatRate(const AutoRepeatRate& rate) override; - virtual bool SetAutoRepeatEnabled(bool enabled) override; - virtual bool GetAutoRepeatEnabled() override; - virtual bool ReapplyCurrentKeyboardLayout() override; - virtual void ReapplyCurrentModifierLockStatus() override; - virtual void DisableNumLock() override; - virtual void SetCapsLockEnabled(bool enable_caps_lock) override; - virtual bool CapsLockIsEnabled() override; + bool SetCurrentKeyboardLayoutByName(const std::string& layout_name) override; + bool SetAutoRepeatRate(const AutoRepeatRate& rate) override; + bool SetAutoRepeatEnabled(bool enabled) override; + bool GetAutoRepeatEnabled() override; + bool ReapplyCurrentKeyboardLayout() override; + void ReapplyCurrentModifierLockStatus() override; + void DisableNumLock() override; + void SetCapsLockEnabled(bool enable_caps_lock) override; + bool CapsLockIsEnabled() override; private: ui::InputController* input_controller_;
diff --git a/ui/base/ime/chromeos/ime_keyboard_x11.cc b/ui/base/ime/chromeos/ime_keyboard_x11.cc index 95c03bd..8b76ed0 100644 --- a/ui/base/ime/chromeos/ime_keyboard_x11.cc +++ b/ui/base/ime/chromeos/ime_keyboard_x11.cc
@@ -173,7 +173,7 @@ PollUntilChildFinish(process.Handle()); DVLOG(1) << "ExecuteSetLayoutCommand: " << layout_to_set - << ": pid=" << process.pid(); + << ": pid=" << process.Pid(); } // Delay and loop until child process finishes and call the callback.
diff --git a/ui/base/ime/input_method_chromeos.cc b/ui/base/ime/input_method_chromeos.cc index 37cfd1e1..aef3e9f 100644 --- a/ui/base/ime/input_method_chromeos.cc +++ b/ui/base/ime/input_method_chromeos.cc
@@ -563,10 +563,11 @@ void InputMethodChromeOS::DeleteSurroundingText(int32 offset, uint32 length) { if (!composition_.text.empty()) return; // do nothing if there is ongoing composition. - if (offset < 0 && static_cast<uint32>(-1 * offset) != length) - return; // only preceding text can be deletable. - if (GetTextInputClient()) - GetTextInputClient()->ExtendSelectionAndDelete(length, 0U); + + if (GetTextInputClient()) { + uint32 before = offset >= 0 ? 0U : static_cast<uint32>(-1 * offset); + GetTextInputClient()->ExtendSelectionAndDelete(before, length - before); + } } bool InputMethodChromeOS::ExecuteCharacterComposer(const ui::KeyEvent& event) {
diff --git a/ui/base/webui/web_ui_util.cc b/ui/base/webui/web_ui_util.cc index 0c5b9f0a..3382a30 100644 --- a/ui/base/webui/web_ui_util.cc +++ b/ui/base/webui/web_ui_util.cc
@@ -12,6 +12,7 @@ #include "base/logging.h" #include "base/memory/ref_counted_memory.h" #include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" #include "net/base/escape.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" @@ -19,6 +20,7 @@ #include "ui/gfx/codec/png_codec.h" #include "ui/gfx/font.h" #include "ui/gfx/image/image_skia.h" +#include "ui/resources/grit/webui_resources.h" #include "ui/strings/grit/app_locale_settings.h" #include "url/gurl.h" @@ -129,6 +131,33 @@ } } +void SetFontAndTextDirection(base::DictionaryValue* localized_strings) { + localized_strings->SetString("fontfamily", GetFontFamily()); + localized_strings->SetString("fontsize", GetFontSize()); + localized_strings->SetString("textdirection", GetTextDirection()); +} + +std::string GetWebUiCssTextDefaults() { + std::vector<std::string> placeholders; + placeholders.push_back(GetTextDirection()); // $1 + placeholders.push_back(GetFontFamily()); // $2 + placeholders.push_back(GetFontSize()); // $3 + + const ui::ResourceBundle& resource_bundle = + ui::ResourceBundle::GetSharedInstance(); + const std::string& css_template = + resource_bundle.GetRawDataResource(IDR_WEBUI_CSS_TEXT_DEFAULTS) + .as_string(); + + return ReplaceStringPlaceholders(css_template, placeholders, nullptr); +} + +void AppendWebUiCssTextDefaults(std::string* html) { + html->append("<style>"); + html->append(GetWebUiCssTextDefaults()); + html->append("</style>"); +} + std::string GetFontFamily() { std::string font_family = l10n_util::GetStringUTF8( #if defined(OS_WIN) @@ -164,10 +193,4 @@ return base::i18n::IsRTL() ? "rtl" : "ltr"; } -void SetFontAndTextDirection(base::DictionaryValue* localized_strings) { - localized_strings->SetString("fontfamily", GetFontFamily()); - localized_strings->SetString("fontsize", GetFontSize()); - localized_strings->SetString("textdirection", GetTextDirection()); -} - } // namespace webui
diff --git a/ui/base/webui/web_ui_util.h b/ui/base/webui/web_ui_util.h index 84e06f3..2dbcfc7 100644 --- a/ui/base/webui/web_ui_util.h +++ b/ui/base/webui/web_ui_util.h
@@ -47,9 +47,20 @@ // Helper function to set the font family, size, and text direction into the // given dictionary. +// Note that using font family and size in JS templates is deprecated, because +// it might lead to flicker. Instead, use AppendWebUICSSTextDefaults() below. +// TODO(bauerb): Remove uses of font-family and font-size in JS templates, then +// rename this method to SetTextDirection(). UI_BASE_EXPORT void SetFontAndTextDirection( base::DictionaryValue* localized_strings); +// Get a CSS declaration for common text styles for all of Web UI. +UI_BASE_EXPORT std::string GetWebUiCssTextDefaults(); + +// Appends the CSS declaration returned by GetWebUiCssTextDefaults() as an +// inline stylesheet. +UI_BASE_EXPORT void AppendWebUiCssTextDefaults(std::string* html); + // Get some common font styles for all of WebUI. UI_BASE_EXPORT std::string GetFontFamily(); UI_BASE_EXPORT std::string GetFontSize();
diff --git a/ui/chromeos/ime/candidate_view.cc b/ui/chromeos/ime/candidate_view.cc index 96b1de6c..db90b6f 100644 --- a/ui/chromeos/ime/candidate_view.cc +++ b/ui/chromeos/ime/candidate_view.cc
@@ -27,6 +27,7 @@ private: ~VerticalCandidateLabel() override {} + // views::Label: // Returns the preferred size, but guarantees that the width has at // least kMinCandidateLabelWidth pixels. gfx::Size GetPreferredSize() const override { @@ -36,6 +37,8 @@ return size; } + const char* GetClassName() const override { return "VerticalCandidateLabel"; } + DISALLOW_COPY_AND_ASSIGN(VerticalCandidateLabel); }; @@ -227,6 +230,10 @@ SetHighlighted(true); } +const char* CandidateView::GetClassName() const { + return "CandidateView"; +} + bool CandidateView::OnMouseDragged(const ui::MouseEvent& event) { if (!HitTestPoint(event.location())) { // Moves the drag target to the sibling view.
diff --git a/ui/chromeos/ime/candidate_view.h b/ui/chromeos/ime/candidate_view.h index e839df4e..bc89160 100644 --- a/ui/chromeos/ime/candidate_view.h +++ b/ui/chromeos/ime/candidate_view.h
@@ -43,6 +43,7 @@ void StateChanged() override; // Overridden from View: + const char* GetClassName() const override; bool OnMouseDragged(const ui::MouseEvent& event) override; void Layout() override; gfx::Size GetPreferredSize() const override;
diff --git a/ui/chromeos/ime/candidate_window_view.cc b/ui/chromeos/ime/candidate_window_view.cc index 823fda5d..7532703 100644 --- a/ui/chromeos/ime/candidate_window_view.cc +++ b/ui/chromeos/ime/candidate_window_view.cc
@@ -392,6 +392,10 @@ candidate_window_.set_cursor_position(cursor_absolute_index); } +const char* CandidateWindowView::GetClassName() const { + return "CandidateWindowView"; +} + void CandidateWindowView::ButtonPressed(views::Button* sender, const ui::Event& event) { for (size_t i = 0; i < candidate_views_.size(); ++i) {
diff --git a/ui/chromeos/ime/candidate_window_view.h b/ui/chromeos/ime/candidate_window_view.h index 4f8efb8..e4846fe 100644 --- a/ui/chromeos/ime/candidate_window_view.h +++ b/ui/chromeos/ime/candidate_window_view.h
@@ -18,7 +18,7 @@ // CandidateWindowView is the main container of the candidate window UI. class UI_CHROMEOS_EXPORT CandidateWindowView : public views::BubbleDelegateView, - public views::ButtonListener { + public views::ButtonListener { public: // The object can be monitored by the observer. class Observer { @@ -73,6 +73,9 @@ private: friend class CandidateWindowViewTest; + // views::BubbleDelegateView: + const char* GetClassName() const override; + // Overridden from views::ButtonListener: void ButtonPressed(views::Button* sender, const ui::Event& event) override;
diff --git a/ui/chromeos/ime/infolist_window.cc b/ui/chromeos/ime/infolist_window.cc index 8c0a2efe..82aea181 100644 --- a/ui/chromeos/ime/infolist_window.cc +++ b/ui/chromeos/ime/infolist_window.cc
@@ -272,6 +272,10 @@ GetWidget()->Close(); } +const char* InfolistWindow::GetClassName() const { + return "InfolistWindow"; +} + void InfolistWindow::WindowClosing() { show_hide_timer_.Stop(); }
diff --git a/ui/chromeos/ime/infolist_window.h b/ui/chromeos/ime/infolist_window.h index bf31a82..1051b96 100644 --- a/ui/chromeos/ime/infolist_window.h +++ b/ui/chromeos/ime/infolist_window.h
@@ -41,6 +41,9 @@ void HideImmediately(); private: + // views::BubbleDelegateView: + const char* GetClassName() const override; + // views::WidgetDelegate implementation. void WindowClosing() override;
diff --git a/ui/chromeos/ime/mode_indicator_view.cc b/ui/chromeos/ime/mode_indicator_view.cc index 8bbb5ddb..609e782 100644 --- a/ui/chromeos/ime/mode_indicator_view.cc +++ b/ui/chromeos/ime/mode_indicator_view.cc
@@ -74,6 +74,10 @@ return size; } +const char* ModeIndicatorView::GetClassName() const { + return "ModeIndicatorView"; +} + void ModeIndicatorView::Init() { SetLayoutManager(new views::FillLayout()); AddChildView(label_view_);
diff --git a/ui/chromeos/ime/mode_indicator_view.h b/ui/chromeos/ime/mode_indicator_view.h index a10169a1..4a2e962 100644 --- a/ui/chromeos/ime/mode_indicator_view.h +++ b/ui/chromeos/ime/mode_indicator_view.h
@@ -35,6 +35,7 @@ protected: // views::BubbleDelegateView override: + const char* GetClassName() const override; void Init() override; // views::WidgetDelegateView overrides:
diff --git a/ui/chromeos/network/network_connect.cc b/ui/chromeos/network/network_connect.cc index a7cb0ae..0d9a3e9 100644 --- a/ui/chromeos/network/network_connect.cc +++ b/ui/chromeos/network/network_connect.cc
@@ -74,8 +74,8 @@ bool shared) override; void CreateConfiguration(base::DictionaryValue* properties, bool shared) override; - base::string16 GetErrorString(const std::string& error, - const std::string& service_path) override; + base::string16 GetShillErrorString(const std::string& error, + const std::string& service_path) override; void ShowNetworkSettings(const std::string& service_path) override; private: @@ -192,18 +192,30 @@ return true; } +// This handles connect failures that are a direct result of a user initiated +// connect request and result in a new UI being shown. Note: notifications are +// handled by NetworkStateNotifier. void NetworkConnectImpl::OnConnectFailed( const std::string& service_path, const std::string& error_name, scoped_ptr<base::DictionaryValue> error_data) { NET_LOG_ERROR("Connect Failed: " + error_name, service_path); - // If a new connect attempt canceled this connect, no need to notify the - // user. - if (error_name == NetworkConnectionHandler::kErrorConnectCanceled) + // If a new connect attempt canceled this connect, or a connect attempt to + // the same network is in progress, no need to notify the user here since they + // will be notified when the new or existing attempt completes. + if (error_name == NetworkConnectionHandler::kErrorConnectCanceled || + error_name == NetworkConnectionHandler::kErrorConnecting) { return; + } - if (error_name == shill::kErrorBadPassphrase || + // Already connected to the network, show the settings UI for the network. + if (error_name == NetworkConnectionHandler::kErrorConnected) { + ShowNetworkSettings(service_path); + return; + } + + if (error_name == NetworkConnectionHandler::kErrorBadPassphrase || error_name == NetworkConnectionHandler::kErrorPassphraseRequired || error_name == NetworkConnectionHandler::kErrorConfigurationRequired || error_name == NetworkConnectionHandler::kErrorAuthenticationRequired) { @@ -212,38 +224,19 @@ } if (error_name == NetworkConnectionHandler::kErrorCertificateRequired) { - if (!delegate_->ShowEnrollNetwork(service_path)) { + if (!delegate_->ShowEnrollNetwork(service_path)) HandleUnconfiguredNetwork(service_path); - } return; } - if (error_name == NetworkConnectionHandler::kErrorActivationRequired) { - ActivateCellular(service_path); - return; - } + // Only show a configure dialog if there was a ConnectFailed error. The dialog + // allows the user to request a new connect attempt or cancel. Note: a + // notification may also be displayed by NetworkStateNotifier in this case. + if (error_name == NetworkConnectionHandler::kErrorConnectFailed) + HandleUnconfiguredNetwork(service_path); - if (error_name == NetworkConnectionHandler::kErrorConnected || - error_name == NetworkConnectionHandler::kErrorConnecting) { - ShowNetworkSettings(service_path); - return; - } - - // ConnectFailed or unknown error; show a notification. - network_state_notifier_->ShowNetworkConnectError(error_name, service_path); - - // Only show a configure dialog if there was a ConnectFailed error. - if (error_name != shill::kErrorConnectFailed) - return; - - // If Shill reports an InProgress error, don't try to configure the network. - std::string dbus_error_name; - error_data.get()->GetString(chromeos::network_handler::kDbusErrorName, - &dbus_error_name); - if (dbus_error_name == shill::kErrorResultInProgress) - return; - - HandleUnconfiguredNetwork(service_path); + // Notifications for other connect failures are handled by + // NetworkStateNotifier, so no need to do anything else here. } void NetworkConnectImpl::OnConnectSucceeded(const std::string& service_path) { @@ -530,7 +523,7 @@ CallCreateConfiguration(properties, shared, false /* connect_on_configure */); } -base::string16 NetworkConnectImpl::GetErrorString( +base::string16 NetworkConnectImpl::GetShillErrorString( const std::string& error, const std::string& service_path) { if (error.empty())
diff --git a/ui/chromeos/network/network_connect.h b/ui/chromeos/network/network_connect.h index 303a79e..80ed818 100644 --- a/ui/chromeos/network/network_connect.h +++ b/ui/chromeos/network/network_connect.h
@@ -96,8 +96,9 @@ bool shared) = 0; // Returns the localized string for shill error string |error|. - virtual base::string16 GetErrorString(const std::string& error, - const std::string& service_path) = 0; + virtual base::string16 GetShillErrorString( + const std::string& error, + const std::string& service_path) = 0; // Shows the settings for the network specified by |service_path|. If empty, // or no matching network exists, shows the general internet settings page.
diff --git a/ui/chromeos/network/network_state_notifier.cc b/ui/chromeos/network/network_state_notifier.cc index a5b5ac5..eb211c2 100644 --- a/ui/chromeos/network/network_state_notifier.cc +++ b/ui/chromeos/network/network_state_notifier.cc
@@ -100,6 +100,7 @@ NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler(); handler->AddObserver(this, FROM_HERE); UpdateDefaultNetwork(handler->DefaultNetwork()); + NetworkHandler::Get()->network_connection_handler()->AddObserver(this); } NetworkStateNotifier::~NetworkStateNotifier() { @@ -107,6 +108,23 @@ return; NetworkHandler::Get()->network_state_handler()->RemoveObserver(this, FROM_HERE); + NetworkHandler::Get()->network_connection_handler()->RemoveObserver(this); +} + +void NetworkStateNotifier::ConnectFailed(const std::string& service_path, + const std::string& error_name) { + // Only show a notification for certain errors. Other failures are expected + // to be handled by the UI that initiated the connect request. + // Note: kErrorConnectFailed may also cause the configure dialog to be + // displayed, but we rely on the notification system to show additional + // details if available. + if (error_name != NetworkConnectionHandler::kErrorConnectFailed && + error_name != NetworkConnectionHandler::kErrorNotFound && + error_name != NetworkConnectionHandler::kErrorConfigureFailed && + error_name != NetworkConnectionHandler::kErrorCertLoadTimeout) { + return; + } + ShowNetworkConnectError(error_name, service_path); } void NetworkStateNotifier::DefaultNetworkChanged(const NetworkState* network) { @@ -316,7 +334,7 @@ return; } - error = network_connect_->GetErrorString(shill_error, service_path); + error = network_connect_->GetShillErrorString(shill_error, service_path); if (error.empty()) error = l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_UNKNOWN); }
diff --git a/ui/chromeos/network/network_state_notifier.h b/ui/chromeos/network/network_state_notifier.h index 129cc472..092e5fe 100644 --- a/ui/chromeos/network/network_state_notifier.h +++ b/ui/chromeos/network/network_state_notifier.h
@@ -12,6 +12,7 @@ #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "base/time/time.h" +#include "chromeos/network/network_connection_observer.h" #include "chromeos/network/network_state_handler_observer.h" #include "ui/chromeos/ui_chromeos_export.h" @@ -34,12 +35,17 @@ // notification system. // 2. It observes NetworkState changes to generate notifications when a // Cellular network is out of credits. -class UI_CHROMEOS_EXPORT NetworkStateNotifier : +class UI_CHROMEOS_EXPORT NetworkStateNotifier + : public chromeos::NetworkConnectionObserver, public chromeos::NetworkStateHandlerObserver { public: explicit NetworkStateNotifier(NetworkConnect* network_connect); ~NetworkStateNotifier() override; + // NetworkConnectionObserver + void ConnectFailed(const std::string& service_path, + const std::string& error_name) override; + // NetworkStateHandlerObserver void DefaultNetworkChanged(const chromeos::NetworkState* network) override; void NetworkPropertiesUpdated(const chromeos::NetworkState* network) override;
diff --git a/ui/compositor/BUILD.gn b/ui/compositor/BUILD.gn index 7bc09ac..6436712 100644 --- a/ui/compositor/BUILD.gn +++ b/ui/compositor/BUILD.gn
@@ -13,7 +13,6 @@ "compositor.h", "compositor_animation_observer.h", "compositor_export.h", - "compositor_observer.cc", "compositor_observer.h", "compositor_vsync_manager.cc", "compositor_vsync_manager.h", @@ -44,6 +43,7 @@ "layer_tree_owner.cc", "layer_tree_owner.h", "layer_type.h", + "reflector.cc", "reflector.h", "scoped_animation_duration_scale_mode.cc", "scoped_animation_duration_scale_mode.h", @@ -88,6 +88,8 @@ "test/draw_waiter_for_test.h", "test/in_process_context_factory.cc", "test/in_process_context_factory.h", + "test/in_process_context_provider.cc", + "test/in_process_context_provider.h", "test/layer_animator_test_controller.cc", "test/layer_animator_test_controller.h", "test/test_compositor_host.h", @@ -113,7 +115,6 @@ "//cc", "//cc/surfaces", "//cc:test_support", - "//gpu/blink", "//skia", "//testing/gtest", "//third_party/WebKit/public:blink_minimal", @@ -121,7 +122,6 @@ "//ui/gfx", "//ui/gfx/geometry", "//ui/gl", - "//webkit/common/gpu", ] if (use_x11) {
diff --git a/ui/compositor/compositor.cc b/ui/compositor/compositor.cc index 0e917265..2363c7c 100644 --- a/ui/compositor/compositor.cc +++ b/ui/compositor/compositor.cc
@@ -175,6 +175,9 @@ CancelCompositorLock(); DCHECK(!compositor_lock_); + FOR_EACH_OBSERVER(CompositorObserver, observer_list_, + OnCompositingShuttingDown(this)); + if (root_layer_) root_layer_->SetCompositor(NULL); @@ -299,25 +302,10 @@ } void Compositor::AddObserver(CompositorObserver* observer) { -#if defined(OS_MACOSX) - // Debugging instrumentation for crbug.com/401630. - // TODO(ccameron): remove this. - CHECK(observer); - if (!observer_list_.HasObserver(observer)) - observer->observing_count_ += 1; -#endif - observer_list_.AddObserver(observer); } void Compositor::RemoveObserver(CompositorObserver* observer) { -#if defined(OS_MACOSX) - // Debugging instrumentation for crbug.com/401630. - // TODO(ccameron): remove this. - if (observer_list_.HasObserver(observer)) - observer->observing_count_ -= 1; -#endif - observer_list_.RemoveObserver(observer); }
diff --git a/ui/compositor/compositor.gyp b/ui/compositor/compositor.gyp index 6959709..796fb40 100644 --- a/ui/compositor/compositor.gyp +++ b/ui/compositor/compositor.gyp
@@ -31,7 +31,6 @@ 'compositor.h', 'compositor_animation_observer.h', 'compositor_export.h', - 'compositor_observer.cc', 'compositor_observer.h', 'compositor_vsync_manager.cc', 'compositor_vsync_manager.h', @@ -62,6 +61,7 @@ 'layer_tree_owner.cc', 'layer_tree_owner.h', 'layer_type.h', + 'reflector.cc', 'reflector.h', 'scoped_animation_duration_scale_mode.cc', 'scoped_animation_duration_scale_mode.h', @@ -90,7 +90,6 @@ '<(DEPTH)/cc/cc.gyp:cc', '<(DEPTH)/cc/cc.gyp:cc_surfaces', '<(DEPTH)/cc/cc_tests.gyp:cc_test_support', - '<(DEPTH)/gpu/blink/gpu_blink.gyp:gpu_blink', '<(DEPTH)/skia/skia.gyp:skia', '<(DEPTH)/testing/gtest.gyp:gtest', '<(DEPTH)/third_party/WebKit/public/blink.gyp:blink_minimal', @@ -98,7 +97,6 @@ '<(DEPTH)/ui/gfx/gfx.gyp:gfx', '<(DEPTH)/ui/gfx/gfx.gyp:gfx_geometry', '<(DEPTH)/ui/gl/gl.gyp:gl', - '<(DEPTH)/webkit/common/gpu/webkit_gpu.gyp:webkit_gpu', 'compositor', ], 'sources': [ @@ -108,6 +106,8 @@ 'test/draw_waiter_for_test.h', 'test/in_process_context_factory.cc', 'test/in_process_context_factory.h', + 'test/in_process_context_provider.cc', + 'test/in_process_context_provider.h', 'test/layer_animator_test_controller.cc', 'test/layer_animator_test_controller.h', 'test/test_compositor_host.h',
diff --git a/ui/compositor/compositor.h b/ui/compositor/compositor.h index 20a8da18..30b77dd 100644 --- a/ui/compositor/compositor.h +++ b/ui/compositor/compositor.h
@@ -314,7 +314,7 @@ // The root of the Layer tree drawn by this compositor. Layer* root_layer_; - ObserverList<CompositorObserver> observer_list_; + ObserverList<CompositorObserver, true> observer_list_; ObserverList<CompositorAnimationObserver> animation_observer_list_; gfx::AcceleratedWidget widget_;
diff --git a/ui/compositor/compositor_observer.cc b/ui/compositor/compositor_observer.cc deleted file mode 100644 index 209cd522..0000000 --- a/ui/compositor/compositor_observer.cc +++ /dev/null
@@ -1,28 +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 "ui/compositor/compositor_observer.h" - -#include "base/logging.h" - -namespace ui { - -#if defined(OS_MACOSX) -// Debugging instrumentation for crbug.com/401630. -// TODO(ccameron): remove this. -CompositorObserver::CompositorObserver() : observing_count_(0) {} -#else -CompositorObserver::CompositorObserver() {} -#endif - -CompositorObserver::~CompositorObserver() { -#if defined(OS_MACOSX) - // Debugging instrumentation for crbug.com/401630. - // TODO(ccameron): remove this. - CHECK_EQ(observing_count_, 0); -#endif -} - -} -
diff --git a/ui/compositor/compositor_observer.h b/ui/compositor/compositor_observer.h index 76b6c5b4..b59a01d 100644 --- a/ui/compositor/compositor_observer.h +++ b/ui/compositor/compositor_observer.h
@@ -15,8 +15,6 @@ // A compositor observer is notified when compositing completes. class COMPOSITOR_EXPORT CompositorObserver { public: - CompositorObserver(); - // A commit proxies information from the main thread to the compositor // thread. It typically happens when some state changes that will require a // composite. In the multi-threaded case, many commits may happen between @@ -40,15 +38,9 @@ // Called when the compositor lock state changes. virtual void OnCompositingLockStateChanged(Compositor* compositor) = 0; - protected: -#if defined(OS_MACOSX) - // Debugging instrumentation for crbug.com/401630. - // TODO(ccameron): remove this. - friend class Compositor; - int32 observing_count_; -#endif - - virtual ~CompositorObserver(); + // Called at the top of the compositor's destructor, to give observers a + // chance to remove themselves. + virtual void OnCompositingShuttingDown(Compositor* compositor) = 0; }; } // namespace ui
diff --git a/ui/compositor/layer.cc b/ui/compositor/layer.cc index 947cf62..13ded04d 100644 --- a/ui/compositor/layer.cc +++ b/ui/compositor/layer.cc
@@ -557,6 +557,16 @@ texture_layer_->SetNeedsDisplay(); } +void Layer::SetTextureFlipped(bool flipped) { + DCHECK(texture_layer_.get()); + texture_layer_->SetFlipped(flipped); +} + +bool Layer::TextureFlipped() const { + DCHECK(texture_layer_.get()); + return texture_layer_->flipped(); +} + void Layer::SetShowDelegatedContent(cc::DelegatedFrameProvider* frame_provider, gfx::Size frame_size_in_dip) { DCHECK(type_ == LAYER_TEXTURED || type_ == LAYER_SOLID_COLOR); @@ -719,7 +729,7 @@ void Layer::PaintContents(SkCanvas* sk_canvas, const gfx::Rect& clip, ContentLayerClient::GraphicsContextStatus gc_status) { - TRACE_EVENT0("ui", "Layer::PaintContents"); + TRACE_EVENT1("ui", "Layer::PaintContents", "name", name_); scoped_ptr<gfx::Canvas> canvas(gfx::Canvas::CreateCanvasWithoutScaling( sk_canvas, device_scale_factor_)); if (delegate_)
diff --git a/ui/compositor/layer.h b/ui/compositor/layer.h index 97c7535..d49101b 100644 --- a/ui/compositor/layer.h +++ b/ui/compositor/layer.h
@@ -274,6 +274,8 @@ scoped_ptr<cc::SingleReleaseCallback> release_callback, gfx::Size texture_size_in_dip); void SetTextureSize(gfx::Size texture_size_in_dip); + void SetTextureFlipped(bool flipped); + bool TextureFlipped() const; // Begins showing delegated frames from the |frame_provider|. void SetShowDelegatedContent(cc::DelegatedFrameProvider* frame_provider,
diff --git a/ui/compositor/layer_animator.cc b/ui/compositor/layer_animator.cc index adff73f..77cfc3b 100644 --- a/ui/compositor/layer_animator.cc +++ b/ui/compositor/layer_animator.cc
@@ -759,10 +759,7 @@ return false; } - // All clear, actually start the sequence. Note: base::TimeTicks::Now has - // a resolution that can be as bad as 15ms. If this causes glitches in the - // animations, this can be switched to HighResNow() (animation uses Now() - // internally). + // All clear, actually start the sequence. // All LayerAnimators share the same LayerAnimatorCollection. Use the // last_tick_time() from there to ensure animations started during the same // event complete at the same time.
diff --git a/ui/compositor/layer_unittest.cc b/ui/compositor/layer_unittest.cc index 57e1e02..77ea7f2 100644 --- a/ui/compositor/layer_unittest.cc +++ b/ui/compositor/layer_unittest.cc
@@ -344,6 +344,8 @@ void OnCompositingLockStateChanged(Compositor* compositor) override {} + void OnCompositingShuttingDown(Compositor* compositor) override {} + bool committed_; bool started_; bool ended_;
diff --git a/ui/compositor/reflector.cc b/ui/compositor/reflector.cc new file mode 100644 index 0000000..f25136d --- /dev/null +++ b/ui/compositor/reflector.cc
@@ -0,0 +1,18 @@ +// Copyright 2015 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 "ui/compositor/reflector.h" + +namespace ui { + +Reflector::Reflector() { +} + +Reflector::~Reflector() { +} + +void Reflector::OnMirroringCompositorResized() { +} + +} // namespace ui
diff --git a/ui/compositor/reflector.h b/ui/compositor/reflector.h index 4145695..6423c26 100644 --- a/ui/compositor/reflector.h +++ b/ui/compositor/reflector.h
@@ -6,18 +6,20 @@ #define UI_COMPOSITOR_REFLECTOR_H_ #include "base/memory/ref_counted.h" +#include "ui/compositor/compositor_export.h" namespace ui { -class Reflector : public base::RefCountedThreadSafe<Reflector> { +class COMPOSITOR_EXPORT Reflector + : public base::RefCountedThreadSafe<Reflector> { public: - Reflector() {} + Reflector(); - virtual void OnMirroringCompositorResized() {} + virtual void OnMirroringCompositorResized(); protected: friend class base::RefCountedThreadSafe<Reflector>; - virtual ~Reflector() {} + virtual ~Reflector(); DISALLOW_COPY_AND_ASSIGN(Reflector); };
diff --git a/ui/compositor/test/DEPS b/ui/compositor/test/DEPS index 7f9b273..bc87fe1b 100644 --- a/ui/compositor/test/DEPS +++ b/ui/compositor/test/DEPS
@@ -1,5 +1,6 @@ include_rules = [ - "+gpu/blink", "+gpu/command_buffer/client", - "+webkit/common/gpu", + "+gpu/command_buffer/common", + "+gpu/skia_bindings", + "+skia/ext", ]
diff --git a/ui/compositor/test/draw_waiter_for_test.cc b/ui/compositor/test/draw_waiter_for_test.cc index 7687d66..5ccb090c 100644 --- a/ui/compositor/test/draw_waiter_for_test.cc +++ b/ui/compositor/test/draw_waiter_for_test.cc
@@ -53,4 +53,6 @@ void DrawWaiterForTest::OnCompositingLockStateChanged(Compositor* compositor) {} +void DrawWaiterForTest::OnCompositingShuttingDown(Compositor* compositor) {} + } // namespace ui
diff --git a/ui/compositor/test/draw_waiter_for_test.h b/ui/compositor/test/draw_waiter_for_test.h index 55ca2ff..5576d270 100644 --- a/ui/compositor/test/draw_waiter_for_test.h +++ b/ui/compositor/test/draw_waiter_for_test.h
@@ -27,7 +27,7 @@ private: DrawWaiterForTest(); - ~DrawWaiterForTest() override; + ~DrawWaiterForTest(); void WaitImpl(Compositor* compositor); @@ -38,6 +38,7 @@ void OnCompositingEnded(Compositor* compositor) override; void OnCompositingAborted(Compositor* compositor) override; void OnCompositingLockStateChanged(Compositor* compositor) override; + void OnCompositingShuttingDown(Compositor* compositor) override; scoped_ptr<base::RunLoop> wait_run_loop_;
diff --git a/ui/compositor/test/in_process_context_factory.cc b/ui/compositor/test/in_process_context_factory.cc index e471814..d51120a 100644 --- a/ui/compositor/test/in_process_context_factory.cc +++ b/ui/compositor/test/in_process_context_factory.cc
@@ -13,14 +13,14 @@ #include "cc/surfaces/surface_id_allocator.h" #include "cc/test/pixel_test_output_surface.h" #include "cc/test/test_shared_bitmap_manager.h" -#include "gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.h" #include "gpu/command_buffer/client/context_support.h" #include "gpu/command_buffer/client/gles2_interface.h" +#include "gpu/command_buffer/common/gles2_cmd_utils.h" #include "ui/compositor/compositor_switches.h" #include "ui/compositor/reflector.h" +#include "ui/compositor/test/in_process_context_provider.h" #include "ui/gl/gl_implementation.h" #include "ui/gl/gl_surface.h" -#include "webkit/common/gpu/context_provider_in_process.h" namespace ui { namespace { @@ -86,22 +86,22 @@ base::WeakPtr<Compositor> compositor, bool software_fallback) { DCHECK(!software_fallback); - blink::WebGraphicsContext3D::Attributes attrs; - attrs.depth = false; - attrs.stencil = false; - attrs.antialias = false; - attrs.shareResources = true; + gpu::gles2::ContextCreationAttribHelper attribs; + attribs.alpha_size = 8; + attribs.blue_size = 8; + attribs.green_size = 8; + attribs.red_size = 8; + attribs.depth_size = 0; + attribs.stencil_size = 0; + attribs.samples = 0; + attribs.sample_buffers = 0; + attribs.fail_if_major_perf_caveat = false; + attribs.bind_generates_resource = false; bool lose_context_when_out_of_memory = true; - using gpu_blink::WebGraphicsContext3DInProcessCommandBufferImpl; - scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl> context3d( - WebGraphicsContext3DInProcessCommandBufferImpl::CreateViewContext( - attrs, lose_context_when_out_of_memory, compositor->widget())); - CHECK(context3d); - - using webkit::gpu::ContextProviderInProcess; - scoped_refptr<ContextProviderInProcess> context_provider = - ContextProviderInProcess::Create(context3d.Pass(), "UICompositor"); + scoped_refptr<InProcessContextProvider> context_provider = + InProcessContextProvider::Create(attribs, lose_context_when_out_of_memory, + compositor->widget(), "UICompositor"); if (use_test_surface_) { bool flipped_output_surface = false; @@ -129,9 +129,8 @@ return shared_main_thread_contexts_; bool lose_context_when_out_of_memory = false; - shared_main_thread_contexts_ = - webkit::gpu::ContextProviderInProcess::CreateOffscreen( - lose_context_when_out_of_memory); + shared_main_thread_contexts_ = InProcessContextProvider::CreateOffscreen( + lose_context_when_out_of_memory); if (shared_main_thread_contexts_.get() && !shared_main_thread_contexts_->BindToCurrentThread()) shared_main_thread_contexts_ = NULL;
diff --git a/ui/compositor/test/in_process_context_factory.h b/ui/compositor/test/in_process_context_factory.h index 23f7d48..7ac9f92 100644 --- a/ui/compositor/test/in_process_context_factory.h +++ b/ui/compositor/test/in_process_context_factory.h
@@ -13,12 +13,6 @@ class Thread; } -namespace webkit { -namespace gpu { -class ContextProviderWebContext; -} -} - namespace ui { class InProcessContextFactory : public ContextFactory { @@ -52,8 +46,7 @@ private: scoped_ptr<base::Thread> compositor_thread_; - scoped_refptr<webkit::gpu::ContextProviderWebContext> - shared_main_thread_contexts_; + scoped_refptr<cc::ContextProvider> shared_main_thread_contexts_; cc::TestSharedBitmapManager shared_bitmap_manager_; cc::TestGpuMemoryBufferManager gpu_memory_buffer_manager_; uint32_t next_surface_id_namespace_;
diff --git a/ui/compositor/test/in_process_context_provider.cc b/ui/compositor/test/in_process_context_provider.cc new file mode 100644 index 0000000..3ad21956 --- /dev/null +++ b/ui/compositor/test/in_process_context_provider.cc
@@ -0,0 +1,224 @@ +// Copyright (c) 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 "ui/compositor/test/in_process_context_provider.h" + +#include "base/bind.h" +#include "base/callback_helpers.h" +#include "base/debug/trace_event.h" +#include "base/lazy_instance.h" +#include "base/strings/stringprintf.h" +#include "cc/output/managed_memory_policy.h" +#include "gpu/command_buffer/client/gl_in_process_context.h" +#include "gpu/command_buffer/client/gles2_implementation.h" +#include "gpu/command_buffer/client/gles2_lib.h" +#include "gpu/skia_bindings/gl_bindings_skia_cmd_buffer.h" +#include "third_party/skia/include/gpu/GrContext.h" +#include "third_party/skia/include/gpu/gl/GrGLInterface.h" + +namespace ui { + +namespace { + +// Singleton used to initialize and terminate the gles2 library. +class GLES2Initializer { + public: + GLES2Initializer() { gles2::Initialize(); } + + ~GLES2Initializer() { gles2::Terminate(); } + + private: + DISALLOW_COPY_AND_ASSIGN(GLES2Initializer); +}; + +base::LazyInstance<GLES2Initializer> g_gles2_initializer = + LAZY_INSTANCE_INITIALIZER; + +} // namespace + +// static +scoped_refptr<InProcessContextProvider> InProcessContextProvider::Create( + const gpu::gles2::ContextCreationAttribHelper& attribs, + bool lose_context_when_out_of_memory, + gfx::AcceleratedWidget window, + const std::string& debug_name) { + return new InProcessContextProvider( + attribs, lose_context_when_out_of_memory, window, debug_name); +} + +// static +scoped_refptr<InProcessContextProvider> +InProcessContextProvider::CreateOffscreen( + bool lose_context_when_out_of_memory) { + gpu::gles2::ContextCreationAttribHelper attribs; + attribs.alpha_size = 8; + attribs.blue_size = 8; + attribs.green_size = 8; + attribs.red_size = 8; + attribs.depth_size = 0; + attribs.stencil_size = 8; + attribs.samples = 0; + attribs.sample_buffers = 0; + attribs.fail_if_major_perf_caveat = false; + attribs.bind_generates_resource = false; + return new InProcessContextProvider( + attribs, lose_context_when_out_of_memory, gfx::kNullAcceleratedWidget, + "Offscreen"); +} + +InProcessContextProvider::InProcessContextProvider( + const gpu::gles2::ContextCreationAttribHelper& attribs, + bool lose_context_when_out_of_memory, + gfx::AcceleratedWidget window, + const std::string& debug_name) + : attribs_(attribs), + lose_context_when_out_of_memory_(lose_context_when_out_of_memory), + window_(window), + debug_name_(debug_name), + destroyed_(false) { + DCHECK(main_thread_checker_.CalledOnValidThread()); + context_thread_checker_.DetachFromThread(); +} + +InProcessContextProvider::~InProcessContextProvider() { + DCHECK(main_thread_checker_.CalledOnValidThread() || + context_thread_checker_.CalledOnValidThread()); +} + +bool InProcessContextProvider::BindToCurrentThread() { + // This is called on the thread the context will be used. + DCHECK(context_thread_checker_.CalledOnValidThread()); + + if (!context_) { + gfx::GpuPreference gpu_preference = gfx::PreferDiscreteGpu; + context_.reset(gpu::GLInProcessContext::Create( + nullptr, /* service */ + nullptr, /* surface */ + true, /* is_offscreen */ + window_, + gfx::Size(1, 1), + nullptr, /* share_context */ + true, /* share_resources */ + attribs_, + gpu_preference, + gpu::GLInProcessContextSharedMemoryLimits(), + nullptr, + nullptr)); + + if (!context_) + return false; + + context_->SetContextLostCallback(base::Bind( + &InProcessContextProvider::OnLostContext, base::Unretained(this))); + } + + capabilities_.gpu = context_->GetImplementation()->capabilities(); + + std::string unique_context_name = + base::StringPrintf("%s-%p", debug_name_.c_str(), context_.get()); + context_->GetImplementation()->TraceBeginCHROMIUM( + "gpu_toplevel", unique_context_name.c_str()); + + return true; +} + +cc::ContextProvider::Capabilities +InProcessContextProvider::ContextCapabilities() { + DCHECK(context_thread_checker_.CalledOnValidThread()); + return capabilities_; +} + +gpu::gles2::GLES2Interface* InProcessContextProvider::ContextGL() { + DCHECK(context_thread_checker_.CalledOnValidThread()); + + return context_->GetImplementation(); +} + +gpu::ContextSupport* InProcessContextProvider::ContextSupport() { + DCHECK(context_thread_checker_.CalledOnValidThread()); + + return context_->GetImplementation(); +} + +static void BindGrContextCallback(const GrGLInterface* interface) { + cc::ContextProvider* context_provider = + reinterpret_cast<InProcessContextProvider*>(interface->fCallbackData); + + gles2::SetGLContext(context_provider->ContextGL()); +} + +class GrContext* InProcessContextProvider::GrContext() { + DCHECK(context_thread_checker_.CalledOnValidThread()); + + if (gr_context_) + return gr_context_.get(); + + // The GrGLInterface factory will make GL calls using the C GLES2 interface. + // Make sure the gles2 library is initialized first on exactly one thread. + g_gles2_initializer.Get(); + gles2::SetGLContext(ContextGL()); + + skia::RefPtr<GrGLInterface> interface = + skia::AdoptRef(skia_bindings::CreateCommandBufferSkiaGLBinding()); + interface->fCallback = BindGrContextCallback; + interface->fCallbackData = reinterpret_cast<GrGLInterfaceCallbackData>(this); + + gr_context_ = skia::AdoptRef(GrContext::Create( + kOpenGL_GrBackend, reinterpret_cast<GrBackendContext>(interface.get()))); + + return gr_context_.get(); +} + +bool InProcessContextProvider::IsContextLost() { + DCHECK(context_thread_checker_.CalledOnValidThread()); + + base::AutoLock lock(destroyed_lock_); + return destroyed_; +} + +void InProcessContextProvider::VerifyContexts() { +} + +void InProcessContextProvider::DeleteCachedResources() { + DCHECK(context_thread_checker_.CalledOnValidThread()); + + if (gr_context_) { + TRACE_EVENT_INSTANT0("gpu", "GrContext::freeGpuResources", + TRACE_EVENT_SCOPE_THREAD); + gr_context_->freeGpuResources(); + } +} + +bool InProcessContextProvider::DestroyedOnMainThread() { + DCHECK(main_thread_checker_.CalledOnValidThread()); + + base::AutoLock lock(destroyed_lock_); + return destroyed_; +} + +void InProcessContextProvider::SetLostContextCallback( + const LostContextCallback& lost_context_callback) { + lost_context_callback_ = lost_context_callback; +} + +void InProcessContextProvider::SetMemoryPolicyChangedCallback( + const MemoryPolicyChangedCallback& memory_policy_changed_callback) { + // There's no memory manager for the in-process implementation. +} + +void InProcessContextProvider::OnLostContext() { + DCHECK(context_thread_checker_.CalledOnValidThread()); + { + base::AutoLock lock(destroyed_lock_); + if (destroyed_) + return; + destroyed_ = true; + } + if (!lost_context_callback_.is_null()) + base::ResetAndReturn(&lost_context_callback_).Run(); + if (gr_context_) + gr_context_->abandonContext(); +} + +} // namespace ui
diff --git a/ui/compositor/test/in_process_context_provider.h b/ui/compositor/test/in_process_context_provider.h new file mode 100644 index 0000000..4b63ed4 --- /dev/null +++ b/ui/compositor/test/in_process_context_provider.h
@@ -0,0 +1,85 @@ +// Copyright (c) 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 WEBKIT_COMMON_GPU_CONTEXT_PROVIDER_IN_PROCESS_H_ +#define WEBKIT_COMMON_GPU_CONTEXT_PROVIDER_IN_PROCESS_H_ + +#include <string> + +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "base/synchronization/lock.h" +#include "base/threading/thread_checker.h" +#include "cc/output/context_provider.h" +#include "gpu/command_buffer/common/gles2_cmd_utils.h" +#include "skia/ext/refptr.h" +#include "ui/gfx/native_widget_types.h" + +namespace gpu { +class GLInProcessContext; +} + +namespace ui { + +class InProcessContextProvider : public cc::ContextProvider { + public: + static scoped_refptr<InProcessContextProvider> Create( + const gpu::gles2::ContextCreationAttribHelper& attribs, + bool lose_context_when_out_of_memory, + gfx::AcceleratedWidget window, + const std::string& debug_name); + + // Uses default attributes for creating an offscreen context. + static scoped_refptr<InProcessContextProvider> CreateOffscreen( + bool lose_context_when_out_of_memory); + + private: + InProcessContextProvider( + const gpu::gles2::ContextCreationAttribHelper& attribs, + bool lose_context_when_out_of_memory, + gfx::AcceleratedWidget window, + const std::string& debug_name); + ~InProcessContextProvider() override; + + // cc::ContextProvider: + bool BindToCurrentThread() override; + Capabilities ContextCapabilities() override; + gpu::gles2::GLES2Interface* ContextGL() override; + gpu::ContextSupport* ContextSupport() override; + class GrContext* GrContext() override; + bool IsContextLost() override; + void VerifyContexts() override; + void DeleteCachedResources() override; + bool DestroyedOnMainThread() override; + void SetLostContextCallback( + const LostContextCallback& lost_context_callback) override; + void SetMemoryPolicyChangedCallback( + const MemoryPolicyChangedCallback& memory_policy_changed_callback) + override; + + void OnLostContext(); + + base::ThreadChecker main_thread_checker_; + base::ThreadChecker context_thread_checker_; + + scoped_ptr<gpu::GLInProcessContext> context_; + skia::RefPtr<class GrContext> gr_context_; + + gpu::gles2::ContextCreationAttribHelper attribs_; + bool lose_context_when_out_of_memory_; + gfx::AcceleratedWidget window_; + std::string debug_name_; + cc::ContextProvider::Capabilities capabilities_; + + LostContextCallback lost_context_callback_; + + base::Lock destroyed_lock_; + bool destroyed_; + + DISALLOW_COPY_AND_ASSIGN(InProcessContextProvider); +}; + +} // namespace ui + +#endif // WEBKIT_COMMON_GPU_CONTEXT_PROVIDER_IN_PROCESS_H_
diff --git a/ui/display/util/edid_parser.cc b/ui/display/util/edid_parser.cc index b95eef4..97aa77c 100644 --- a/ui/display/util/edid_parser.cc +++ b/ui/display/util/edid_parser.cc
@@ -9,6 +9,7 @@ #include "base/hash.h" #include "base/strings/string_util.h" #include "base/sys_byteorder.h" +#include "ui/gfx/geometry/size.h" namespace ui { @@ -37,7 +38,8 @@ std::string product_name; // ParseOutputDeviceData fails if it doesn't have product_name. - ParseOutputDeviceData(edid, &manufacturer_id, &product_name); + ParseOutputDeviceData(edid, &manufacturer_id, &product_name, nullptr, + nullptr); // Generates product specific value from product_name instead of product code. // See crbug.com/240341 @@ -55,7 +57,9 @@ bool ParseOutputDeviceData(const std::vector<uint8_t>& edid, uint16_t* manufacturer_id, - std::string* human_readable_name) { + std::string* human_readable_name, + gfx::Size* active_pixel_out, + gfx::Size* physical_display_size_out) { // See http://en.wikipedia.org/wiki/Extended_display_identification_data // for the details of EDID data format. We use the following data: // bytes 8-9: manufacturer EISA ID, in big-endian @@ -82,15 +86,57 @@ #endif } - if (!human_readable_name) - return true; + if (human_readable_name) + human_readable_name->clear(); - human_readable_name->clear(); for (unsigned int i = 0; i < kNumDescriptors; ++i) { if (edid.size() < kDescriptorOffset + (i + 1) * kDescriptorLength) break; size_t offset = kDescriptorOffset + i * kDescriptorLength; + + // Detailed Timing Descriptor: + if (edid[offset] != 0 && edid[offset + 1] != 0) { + const int kMaxResolution = 10080; // 8k display. + + if (active_pixel_out) { + const int kHorizontalPixelLsbOffset = 2; + const int kHorizontalPixelMsbOffset = 4; + const int kVerticalPixelLsbOffset = 5; + const int kVerticalPixelMsbOffset = 7; + + int h_lsb = edid[offset + kHorizontalPixelLsbOffset]; + int h_msb = edid[offset + kHorizontalPixelMsbOffset]; + int h_pixel = std::min(h_lsb + ((h_msb & 0xF0) << 4), kMaxResolution); + + int v_lsb = edid[offset + kVerticalPixelLsbOffset]; + int v_msb = edid[offset + kVerticalPixelMsbOffset]; + int v_pixel = std::min(v_lsb + ((v_msb & 0xF0) << 4), kMaxResolution); + + active_pixel_out->SetSize(h_pixel, v_pixel); + // EDID may contain multiple DTD. Use first one that + // contains the highest resolution. + active_pixel_out = nullptr; + } + + if (physical_display_size_out) { + const int kHorizontalSizeLsbOffset = 12; + const int kVerticalSizeLsbOffset = 13; + const int kSizeMsbOffset = 14; + + int h_lsb = edid[offset + kHorizontalSizeLsbOffset]; + int v_lsb = edid[offset + kVerticalSizeLsbOffset]; + + int msb = edid[offset + kSizeMsbOffset]; + int h_size = h_lsb + ((msb & 0xF0) << 4); + int v_size = v_lsb + ((msb & 0x0F) << 8); + physical_display_size_out->SetSize(h_size, v_size); + physical_display_size_out = nullptr; + } + continue; + } + + // EDID Other Monitor Descriptors: // If the descriptor contains the display name, it has the following // structure: // bytes 0-2, 4: \0 @@ -99,22 +145,26 @@ // we should check bytes 0-2 and 4, since it may have other values in // case that the descriptor contains other type of data. if (edid[offset] == 0 && edid[offset + 1] == 0 && edid[offset + 2] == 0 && - edid[offset + 3] == kMonitorNameDescriptor && edid[offset + 4] == 0) { + edid[offset + 3] == kMonitorNameDescriptor && edid[offset + 4] == 0 && + human_readable_name) { std::string found_name(reinterpret_cast<const char*>(&edid[offset + 5]), kDescriptorLength - 5); base::TrimWhitespaceASCII( found_name, base::TRIM_TRAILING, human_readable_name); - break; + continue; } } // Verify if the |human_readable_name| consists of printable characters only. - for (size_t i = 0; i < human_readable_name->size(); ++i) { - char c = (*human_readable_name)[i]; - if (!isascii(c) || !isprint(c)) { - human_readable_name->clear(); - LOG(ERROR) << "invalid EDID: human unreadable char in name"; - return false; + // TODO(oshima|muka): Consider replacing unprintable chars with white space. + if (human_readable_name) { + for (size_t i = 0; i < human_readable_name->size(); ++i) { + char c = (*human_readable_name)[i]; + if (!isascii(c) || !isprint(c)) { + human_readable_name->clear(); + LOG(ERROR) << "invalid EDID: human unreadable char in name"; + return false; + } } }
diff --git a/ui/display/util/edid_parser.h b/ui/display/util/edid_parser.h index 4f12d40..447a0c8 100644 --- a/ui/display/util/edid_parser.h +++ b/ui/display/util/edid_parser.h
@@ -12,6 +12,10 @@ #include "ui/display/util/display_util_export.h" +namespace gfx { +class Size; +} + // EDID (Extended Display Identification Data) is a format for monitor // metadata. This provides a parser for the data. @@ -24,14 +28,17 @@ uint8_t index, int64_t* display_id_out); -// Parses |edid| as EDID data and stores extracted data into |manufacturer_id| -// and |human_readable_name| and returns true. NULL can be passed for unwanted -// output parameters. Some devices (especially internal displays) may not have -// the field for |human_readable_name|, and it will return true in that case. +// Parses |edid| as EDID data and stores extracted data into |manufacturer_id|, +// |human_readable_name|, |active_pixel_out| and |physical_display_size_out|, +// then returns true. nullptr can be passed for unwanted output parameters. +// Some devices (especially internal displays) may not have the field for +// |human_readable_name|, and it will return true in that case. DISPLAY_UTIL_EXPORT bool ParseOutputDeviceData( const std::vector<uint8_t>& edid, uint16_t* manufacturer_id, - std::string* human_readable_name); + std::string* human_readable_name, + gfx::Size* active_pixel_out, + gfx::Size* physical_display_size_out); DISPLAY_UTIL_EXPORT bool ParseOutputOverscanFlag( const std::vector<uint8_t>& edid,
diff --git a/ui/display/util/edid_parser_unittest.cc b/ui/display/util/edid_parser_unittest.cc index ef55bd6..30e2bf84 100644 --- a/ui/display/util/edid_parser_unittest.cc +++ b/ui/display/util/edid_parser_unittest.cc
@@ -6,6 +6,7 @@ #include "base/memory/scoped_ptr.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/gfx/geometry/size.h" namespace ui { @@ -93,6 +94,11 @@ "\x50\x20\x4C\x50\x32\x34\x36\x35\x0A\x20\x20\x20\x00\x00\x00\xFF" "\x00\x43\x4E\x4B\x38\x30\x32\x30\x34\x48\x4D\x0A\x20\x20\x00\x45"; +void Reset(gfx::Size* pixel, gfx::Size* size) { + pixel->SetSize(0, 0); + size->SetSize(0, 0); +} + } // namespace TEST(EDIDParserTest, ParseOverscanFlag) { @@ -149,29 +155,42 @@ std::string human_readable_name; std::vector<uint8_t> edid( kNormalDisplay, kNormalDisplay + charsize(kNormalDisplay)); - EXPECT_TRUE(ParseOutputDeviceData( - edid, &manufacturer_id, &human_readable_name)); + gfx::Size pixel; + gfx::Size size; + EXPECT_TRUE(ParseOutputDeviceData(edid, &manufacturer_id, + &human_readable_name, &pixel, &size)); EXPECT_EQ(0x22f0u, manufacturer_id); EXPECT_EQ("HP ZR30w", human_readable_name); + EXPECT_EQ("2560x1600", pixel.ToString()); + EXPECT_EQ("641x400", size.ToString()); manufacturer_id = 0; human_readable_name.clear(); + Reset(&pixel, &size); edid.assign(kInternalDisplay, kInternalDisplay + charsize(kInternalDisplay)); - EXPECT_TRUE(ParseOutputDeviceData(edid, &manufacturer_id, NULL)); + + EXPECT_TRUE( + ParseOutputDeviceData(edid, &manufacturer_id, nullptr, &pixel, &size)); EXPECT_EQ(0x4ca3u, manufacturer_id); EXPECT_EQ("", human_readable_name); + EXPECT_EQ("1280x800", pixel.ToString()); + EXPECT_EQ("261x163", size.ToString()); // Internal display doesn't have name. - EXPECT_TRUE(ParseOutputDeviceData(edid, NULL, &human_readable_name)); + EXPECT_TRUE(ParseOutputDeviceData(edid, nullptr, &human_readable_name, &pixel, + &size)); EXPECT_TRUE(human_readable_name.empty()); manufacturer_id = 0; human_readable_name.clear(); + Reset(&pixel, &size); edid.assign(kOverscanDisplay, kOverscanDisplay + charsize(kOverscanDisplay)); - EXPECT_TRUE(ParseOutputDeviceData( - edid, &manufacturer_id, &human_readable_name)); + EXPECT_TRUE(ParseOutputDeviceData(edid, &manufacturer_id, + &human_readable_name, &pixel, &size)); EXPECT_EQ(0x4c2du, manufacturer_id); EXPECT_EQ("SAMSUNG", human_readable_name); + EXPECT_EQ("1920x1080", pixel.ToString()); + EXPECT_EQ("160x90", size.ToString()); } TEST(EDIDParserTest, ParseBrokenEDID) { @@ -179,9 +198,11 @@ std::string human_readable_name; std::vector<uint8_t> edid; + gfx::Size dummy; + // length == 0 - EXPECT_FALSE(ParseOutputDeviceData( - edid, &manufacturer_id, &human_readable_name)); + EXPECT_FALSE(ParseOutputDeviceData(edid, &manufacturer_id, + &human_readable_name, &dummy, &dummy)); // name is broken. Copying kNormalDisplay and substitute its name data by // some control code. @@ -190,12 +211,13 @@ // display's name data is embedded in byte 95-107 in this specific example. // Fix here too when the contents of kNormalDisplay is altered. edid[97] = '\x1b'; - EXPECT_FALSE(ParseOutputDeviceData( - edid, &manufacturer_id, &human_readable_name)); + EXPECT_FALSE(ParseOutputDeviceData(edid, &manufacturer_id, + &human_readable_name, &dummy, &dummy)); // If |human_readable_name| isn't specified, it skips parsing the name. manufacturer_id = 0; - EXPECT_TRUE(ParseOutputDeviceData(edid, &manufacturer_id, NULL)); + EXPECT_TRUE( + ParseOutputDeviceData(edid, &manufacturer_id, nullptr, &dummy, &dummy)); EXPECT_EQ(0x22f0u, manufacturer_id); }
diff --git a/ui/display/util/x11/edid_parser_x11.cc b/ui/display/util/x11/edid_parser_x11.cc index 407639b..47f8fb6 100644 --- a/ui/display/util/x11/edid_parser_x11.cc +++ b/ui/display/util/x11/edid_parser_x11.cc
@@ -54,7 +54,7 @@ int actual_format; unsigned long bytes_after; unsigned long nitems = 0; - unsigned char* prop = NULL; + unsigned char* prop = nullptr; XRRGetOutputProperty(display, output, edid_property, @@ -78,7 +78,7 @@ // Gets some useful data from the specified output device, such like // manufacturer's ID, product code, and human readable name. Returns false if it // fails to get those data and doesn't touch manufacturer ID/product code/name. -// NULL can be passed for unwanted output parameters. +// nullptr can be passed for unwanted output parameters. bool GetOutputDeviceData(XID output, uint16_t* manufacturer_id, std::string* human_readable_name) { @@ -86,9 +86,8 @@ if (!GetEDIDProperty(output, &edid)) return false; - bool result = ParseOutputDeviceData( - edid, manufacturer_id, human_readable_name); - return result; + return ParseOutputDeviceData(edid, manufacturer_id, human_readable_name, + nullptr, nullptr); } } // namespace @@ -106,7 +105,7 @@ std::string GetDisplayName(RROutput output) { std::string display_name; - GetOutputDeviceData(output, NULL, &display_name); + GetOutputDeviceData(output, nullptr, &display_name); return display_name; }
diff --git a/ui/events/event_dispatcher_unittest.cc b/ui/events/event_dispatcher_unittest.cc index 52becb5..95b45a30 100644 --- a/ui/events/event_dispatcher_unittest.cc +++ b/ui/events/event_dispatcher_unittest.cc
@@ -43,7 +43,7 @@ EventTarget* GetParentTarget() override { return parent_; } scoped_ptr<EventTargetIterator> GetChildIterator() const override { - return scoped_ptr<EventTargetIterator>(); + return nullptr; } EventTargeter* GetEventTargeter() override { return NULL; }
diff --git a/ui/events/gestures/motion_event_aura.cc b/ui/events/gestures/motion_event_aura.cc index 2f532e7..174918fed 100644 --- a/ui/events/gestures/motion_event_aura.cc +++ b/ui/events/gestures/motion_event_aura.cc
@@ -82,12 +82,17 @@ bool pointer_id_is_active = index != -1; if (touch.type() == ET_TOUCH_PRESSED && pointer_id_is_active) { - // Ignore touch press events if we already believe the pointer is down. - - // TODO(tdresser): this should return false (or NOTREACHED()); - // however, there is at least one case where we need to allow a - // touch press from a currently used touch id. See + // TODO(tdresser): This should return false (or NOTREACHED()), and + // ignore the touch; however, there is at least one case where we + // need to allow a touch press from a currently used touch id. See // crbug.com/446852 for details. + + // Cancel the existing touch, before handling the touch press. + TouchEvent cancel(ET_TOUCH_CANCELLED, touch.location(), touch.touch_id(), + touch.time_stamp()); + OnTouch(cancel); + CleanupRemovedTouchPoints(cancel); + DCHECK_EQ(-1, FindPointerIndexOfId(touch.touch_id())); } else if (touch.type() != ET_TOUCH_PRESSED && !pointer_id_is_active) { // We could have an active touch stream transfered to us, resulting in touch // move or touch up events without associated touch down events. Ignore
diff --git a/ui/events/gestures/motion_event_aura_unittest.cc b/ui/events/gestures/motion_event_aura_unittest.cc index 57ee6ce..8decac0 100644 --- a/ui/events/gestures/motion_event_aura_unittest.cc +++ b/ui/events/gestures/motion_event_aura_unittest.cc
@@ -456,10 +456,20 @@ // Once crbug.com/446852 is fixed, we should ignore redundant presses. TEST(MotionEventAuraTest, DoesntIgnoreRedundantPresses) { - int id = 7; + const int id = 7; + const int position_1 = 10; + const int position_2 = 23; + MotionEventAura event; - EXPECT_TRUE(event.OnTouch(TouchWithType(ET_TOUCH_PRESSED, id))); - EXPECT_TRUE(event.OnTouch(TouchWithType(ET_TOUCH_PRESSED, id))); + TouchEvent press1 = TouchWithPosition(ET_TOUCH_PRESSED, id, position_1, + position_1, position_1, position_1); + EXPECT_TRUE(event.OnTouch(press1)); + TouchEvent press2 = TouchWithPosition(ET_TOUCH_PRESSED, id, position_2, + position_2, position_2, position_2); + EXPECT_TRUE(event.OnTouch(press2)); + + EXPECT_EQ(1U, event.GetPointerCount()); + EXPECT_FLOAT_EQ(position_2, event.GetX(0)); } TEST(MotionEventAuraTest, IgnoresEventsWithoutPress) {
diff --git a/ui/events/latency_info.cc b/ui/events/latency_info.cc index 6050d26..b6478f49 100644 --- a/ui/events/latency_info.cc +++ b/ui/events/latency_info.cc
@@ -201,7 +201,7 @@ int64 id, int64 component_sequence_number) { AddLatencyNumberWithTimestamp(component, id, component_sequence_number, - base::TimeTicks::HighResNow(), 1); + base::TimeTicks::Now(), 1); } void LatencyInfo::AddLatencyNumberWithTimestamp(LatencyComponentType component, @@ -238,7 +238,7 @@ // CrOS). So we need to adjust the diff between in CLOCK_MONOTONIC and // CLOCK_SYSTEM_TRACE. Note that the diff is drifting overtime so we // can't use a static value. - int64 diff = base::TimeTicks::HighResNow().ToInternalValue() - + int64 diff = base::TimeTicks::Now().ToInternalValue() - base::TimeTicks::NowFromSystemTraceTime().ToInternalValue(); ts = component.event_time.ToInternalValue() - diff; } else { @@ -252,7 +252,7 @@ } TRACE_EVENT_FLOW_BEGIN0( - "input", "LatencyInfo.Flow", TRACE_ID_DONT_MANGLE(trace_id)); + "input,benchmark", "LatencyInfo.Flow", TRACE_ID_DONT_MANGLE(trace_id)); } LatencyMap::key_type key = std::make_pair(component, id); @@ -287,7 +287,7 @@ } TRACE_EVENT_FLOW_END0( - "input", "LatencyInfo.Flow", TRACE_ID_DONT_MANGLE(trace_id)); + "input,benchmark", "LatencyInfo.Flow", TRACE_ID_DONT_MANGLE(trace_id)); } }
diff --git a/ui/events/ozone/BUILD.gn b/ui/events/ozone/BUILD.gn index 5ddb911b..6398faf 100644 --- a/ui/events/ozone/BUILD.gn +++ b/ui/events/ozone/BUILD.gn
@@ -68,6 +68,8 @@ "evdev/event_converter_evdev_impl.h", "evdev/event_device_info.cc", "evdev/event_device_info.h", + "evdev/event_dispatch_callback.cc", + "evdev/event_dispatch_callback.h", "evdev/event_factory_evdev.cc", "evdev/event_factory_evdev.h", "evdev/event_modifiers_evdev.cc",
diff --git a/ui/events/ozone/device/device_manager_manual.cc b/ui/events/ozone/device/device_manager_manual.cc index c86ffccf..f5e1eca 100644 --- a/ui/events/ozone/device/device_manager_manual.cc +++ b/ui/events/ozone/device/device_manager_manual.cc
@@ -4,30 +4,71 @@ #include "ui/events/ozone/device/device_manager_manual.h" +#include "base/bind.h" +#include "base/callback.h" #include "base/files/file_enumerator.h" +#include "base/location.h" +#include "base/threading/worker_pool.h" #include "ui/events/ozone/device/device_event.h" #include "ui/events/ozone/device/device_event_observer.h" namespace ui { -DeviceManagerManual::DeviceManagerManual() {} +namespace { -DeviceManagerManual::~DeviceManagerManual() {} - -void DeviceManagerManual::ScanDevices(DeviceEventObserver* observer) { +void ScanDevicesOnWorkerThread(std::vector<base::FilePath>* result) { base::FileEnumerator file_enum(base::FilePath("/dev/input"), false, base::FileEnumerator::FILES, "event*[0-9]"); for (base::FilePath path = file_enum.Next(); !path.empty(); path = file_enum.Next()) { - DeviceEvent event(DeviceEvent::INPUT, DeviceEvent::ADD, path); - observer->OnDeviceEvent(event); + result->push_back(path); + } +} +} + +DeviceManagerManual::DeviceManagerManual() + : have_scanned_devices_(false), weak_ptr_factory_(this) { +} + +DeviceManagerManual::~DeviceManagerManual() { +} + +void DeviceManagerManual::ScanDevices(DeviceEventObserver* observer) { + if (have_scanned_devices_) { + std::vector<base::FilePath>::const_iterator it = devices_.begin(); + for (; it != devices_.end(); ++it) { + DeviceEvent event(DeviceEvent::INPUT, DeviceEvent::ADD, *it); + observer->OnDeviceEvent(event); + } + } else { + std::vector<base::FilePath>* result = new std::vector<base::FilePath>(); + base::WorkerPool::PostTaskAndReply( + FROM_HERE, base::Bind(&ScanDevicesOnWorkerThread, result), + base::Bind(&DeviceManagerManual::OnDevicesScanned, + weak_ptr_factory_.GetWeakPtr(), base::Owned(result)), + false /* task_is_slow */); + have_scanned_devices_ = true; } } -void DeviceManagerManual::AddObserver(DeviceEventObserver* observer) {} +void DeviceManagerManual::AddObserver(DeviceEventObserver* observer) { + observers_.AddObserver(observer); +} -void DeviceManagerManual::RemoveObserver(DeviceEventObserver* observer) {} +void DeviceManagerManual::RemoveObserver(DeviceEventObserver* observer) { + observers_.RemoveObserver(observer); +} + +void DeviceManagerManual::OnDevicesScanned( + std::vector<base::FilePath>* result) { + std::vector<base::FilePath>::const_iterator it = result->begin(); + for (; it != result->end(); ++it) { + devices_.push_back(*it); + DeviceEvent event(DeviceEvent::INPUT, DeviceEvent::ADD, *it); + FOR_EACH_OBSERVER(DeviceEventObserver, observers_, OnDeviceEvent(event)); + } +} } // namespace ui
diff --git a/ui/events/ozone/device/device_manager_manual.h b/ui/events/ozone/device/device_manager_manual.h index 09e9875b..d158365 100644 --- a/ui/events/ozone/device/device_manager_manual.h +++ b/ui/events/ozone/device/device_manager_manual.h
@@ -5,9 +5,16 @@ #ifndef UI_EVENTS_OZONE_DEVICE_DEVICE_MANAGER_MANUAL_H_ #define UI_EVENTS_OZONE_DEVICE_DEVICE_MANAGER_MANUAL_H_ +#include <vector> + #include "base/macros.h" +#include "base/observer_list.h" #include "ui/events/ozone/device/device_manager.h" +namespace base { +class FilePath; +} + namespace ui { class DeviceManagerManual : public DeviceManager { @@ -21,6 +28,14 @@ void AddObserver(DeviceEventObserver* observer) override; void RemoveObserver(DeviceEventObserver* observer) override; + void OnDevicesScanned(std::vector<base::FilePath>* result); + + bool have_scanned_devices_; + std::vector<base::FilePath> devices_; + ObserverList<DeviceEventObserver> observers_; + + base::WeakPtrFactory<DeviceManagerManual> weak_ptr_factory_; + DISALLOW_COPY_AND_ASSIGN(DeviceManagerManual); };
diff --git a/ui/events/ozone/device/udev/device_manager_udev.cc b/ui/events/ozone/device/udev/device_manager_udev.cc index 432173d..4207082 100644 --- a/ui/events/ozone/device/udev/device_manager_udev.cc +++ b/ui/events/ozone/device/udev/device_manager_udev.cc
@@ -158,7 +158,7 @@ device::udev_device_get_property_value(device, "SUBSYSTEM"); if (!path || !subsystem) - return scoped_ptr<DeviceEvent>(); + return nullptr; DeviceEvent::DeviceType device_type; if (!strcmp(subsystem, "input") && @@ -168,7 +168,7 @@ StartsWithASCII(path, "/dev/dri/card", true)) device_type = DeviceEvent::DISPLAY; else - return scoped_ptr<DeviceEvent>(); + return nullptr; DeviceEvent::ActionType action_type; if (!action || !strcmp(action, "add")) @@ -178,9 +178,9 @@ else if (!strcmp(action, "change")) action_type = DeviceEvent::CHANGE; else - return scoped_ptr<DeviceEvent>(); + return nullptr; - return scoped_ptr<DeviceEvent>( + return make_scoped_ptr( new DeviceEvent(device_type, action_type, base::FilePath(path))); }
diff --git a/ui/events/ozone/evdev/event_dispatch_callback.cc b/ui/events/ozone/evdev/event_dispatch_callback.cc new file mode 100644 index 0000000..aa2fcce --- /dev/null +++ b/ui/events/ozone/evdev/event_dispatch_callback.cc
@@ -0,0 +1,30 @@ +// 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 "ui/events/ozone/evdev/event_dispatch_callback.h" + +namespace ui { + +TouchEventParams::TouchEventParams(int device_id, + int touch_id, + EventType type, + const gfx::PointF& location, + const gfx::Vector2dF& radii, + float pressure, + const base::TimeDelta& timestamp) + : device_id(device_id), + touch_id(touch_id), + type(type), + location(location), + radii(radii), + pressure(pressure), + timestamp(timestamp) { +} + +TouchEventParams::TouchEventParams(const TouchEventParams& other) = default; + +TouchEventParams::~TouchEventParams() { +} + +} // namspace ui
diff --git a/ui/events/ozone/evdev/event_dispatch_callback.h b/ui/events/ozone/evdev/event_dispatch_callback.h index ae07817..487c9a0 100644 --- a/ui/events/ozone/evdev/event_dispatch_callback.h +++ b/ui/events/ozone/evdev/event_dispatch_callback.h
@@ -6,6 +6,20 @@ #define UI_EVENTS_OZONE_EVDEV_EVENT_DISPATCH_CALLBACK_H_ #include "base/callback.h" +#include "base/time/time.h" +#include "ui/events/event_constants.h" +#include "ui/events/ozone/evdev/events_ozone_evdev_export.h" +#include "ui/gfx/geometry/point_f.h" +#include "ui/gfx/geometry/vector2d_f.h" + +namespace base { +class TimeDelta; +} + +namespace gfx { +class PointF; +class Vector2dF; +} namespace ui { @@ -13,6 +27,29 @@ typedef base::Callback<void(scoped_ptr<Event>)> EventDispatchCallback; +struct EVENTS_OZONE_EVDEV_EXPORT TouchEventParams { + TouchEventParams(int device_id, + int touch_id, + EventType type, + const gfx::PointF& location, + const gfx::Vector2dF& radii, + float pressure, + const base::TimeDelta& timestamp); + TouchEventParams(const TouchEventParams& other); + ~TouchEventParams(); + + int device_id; + int touch_id; + EventType type; + gfx::PointF location; + gfx::Vector2dF radii; + float pressure; + base::TimeDelta timestamp; +}; + +typedef base::Callback<void(const TouchEventParams& params)> + TouchEventDispatchCallback; + } // namspace ui #endif // UI_EVENTS_OZONE_EVDEV_EVENT_DISPATCH_CALLBACK_H_
diff --git a/ui/events/ozone/evdev/event_factory_evdev.cc b/ui/events/ozone/evdev/event_factory_evdev.cc index ea8766d1..a2d60ae 100644 --- a/ui/events/ozone/evdev/event_factory_evdev.cc +++ b/ui/events/ozone/evdev/event_factory_evdev.cc
@@ -7,11 +7,13 @@ #include <fcntl.h> #include <linux/input.h> +#include "base/bind.h" #include "base/debug/trace_event.h" #include "base/stl_util.h" #include "base/task_runner.h" #include "base/thread_task_runner_handle.h" #include "base/threading/worker_pool.h" +#include "base/time/time.h" #include "ui/events/devices/device_data_manager.h" #include "ui/events/devices/device_util_linux.h" #include "ui/events/devices/input_device.h" @@ -49,6 +51,7 @@ // Callback for dispatching events. Call on UI thread only. EventDispatchCallback dispatch_callback; + TouchEventDispatchCallback touch_callback; // State shared between devices. Must not be dereferenced on worker thread. EventModifiersEvdev* modifiers; @@ -94,7 +97,7 @@ // Touchscreen: use TouchEventConverterEvdev. if (devinfo.HasMTAbsXY()) { scoped_ptr<TouchEventConverterEvdev> converter(new TouchEventConverterEvdev( - fd, params.path, params.id, type, params.dispatch_callback)); + fd, params.path, params.id, type, params.touch_callback)); converter->Initialize(devinfo); return converter.Pass(); } @@ -197,6 +200,28 @@ &modifiers_, cursor_, &keyboard_, dispatch_callback_)); } +void EventFactoryEvdev::PostTouchEvent(const TouchEventParams& params) { + float x = params.location.x(); + float y = params.location.y(); + double radius_x = params.radii.x(); + double radius_y = params.radii.y(); + + // Transform the event to align touches to the image based on display mode. + DeviceDataManager::GetInstance()->ApplyTouchTransformer(params.device_id, &x, + &y); + DeviceDataManager::GetInstance()->ApplyTouchRadiusScale(params.device_id, + &radius_x); + DeviceDataManager::GetInstance()->ApplyTouchRadiusScale(params.device_id, + &radius_y); + + scoped_ptr<TouchEvent> touch_event(new TouchEvent( + params.type, gfx::PointF(x, y), + /* flags */ 0, params.touch_id, params.timestamp, radius_x, radius_y, + /* angle */ 0., params.pressure)); + touch_event->set_source_device_id(params.device_id); + PostUiEvent(touch_event.Pass()); +} + void EventFactoryEvdev::PostUiEvent(scoped_ptr<Event> event) { base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, @@ -245,6 +270,10 @@ params->button_map = &button_map_; params->keyboard = &keyboard_; params->cursor = cursor_; + + params->touch_callback = base::Bind(&EventFactoryEvdev::PostTouchEvent, + weak_ptr_factory_.GetWeakPtr()); + #if defined(USE_EVDEV_GESTURES) params->gesture_property_provider = gesture_property_provider_.get(); #endif
diff --git a/ui/events/ozone/evdev/event_factory_evdev.h b/ui/events/ozone/evdev/event_factory_evdev.h index b8933566..e09f497 100644 --- a/ui/events/ozone/evdev/event_factory_evdev.h +++ b/ui/events/ozone/evdev/event_factory_evdev.h
@@ -78,6 +78,9 @@ InputController* input_controller() { return &input_controller_; } + // Post a touch event to UI. + void PostTouchEvent(const TouchEventParams& params); + protected: // DeviceEventObserver overrides: //
diff --git a/ui/events/ozone/evdev/touch_event_converter_evdev.cc b/ui/events/ozone/evdev/touch_event_converter_evdev.cc index 21c5880..57f5ca8 100644 --- a/ui/events/ozone/evdev/touch_event_converter_evdev.cc +++ b/ui/events/ozone/evdev/touch_event_converter_evdev.cc
@@ -74,9 +74,9 @@ base::FilePath path, int id, InputDeviceType type, - const EventDispatchCallback& callback) + const TouchEventDispatchCallback& touch_callback) : EventConverterEvdev(fd, path, id, type), - callback_(callback), + touch_callback_(touch_callback), syn_dropped_(false), is_type_a_(false), current_slot_(0) { @@ -270,35 +270,12 @@ } void TouchEventConverterEvdev::ReportEvent(int touch_id, - const InProgressEvents& event, const base::TimeDelta& delta) { - float x = event.x_; - float y = event.y_; - - double radius_x = event.radius_x_; - double radius_y = event.radius_y_; - - // Transform the event according (this is used to align touches - // to the image based on display mode). - DeviceDataManager::GetInstance()->ApplyTouchTransformer( - id_, &x, &y); - DeviceDataManager::GetInstance()->ApplyTouchRadiusScale( - id_, &radius_x); - DeviceDataManager::GetInstance()->ApplyTouchRadiusScale( - id_, &radius_y); - - gfx::PointF location(x, y); - - scoped_ptr<TouchEvent> touch_event( - new TouchEvent(event.type_, location, - /* flags */ 0, - /* touch_id */ touch_id, - delta, - /* radius_x */ radius_x, - /* radius_y */ radius_y, - /* angle */ 0., - event.pressure_)); - touch_event->set_source_device_id(id_); - callback_.Run(touch_event.Pass()); + const InProgressEvents& event, + const base::TimeDelta& timestamp) { + touch_callback_.Run(TouchEventParams( + id_, touch_id, event.type_, gfx::PointF(event.x_, event.y_), + gfx::Vector2dF(event.radius_x_, event.radius_y_), event.pressure_, + timestamp)); } void TouchEventConverterEvdev::ReportEvents(base::TimeDelta delta) {
diff --git a/ui/events/ozone/evdev/touch_event_converter_evdev.h b/ui/events/ozone/evdev/touch_event_converter_evdev.h index c78645c..f27d18de 100644 --- a/ui/events/ozone/evdev/touch_event_converter_evdev.h +++ b/ui/events/ozone/evdev/touch_event_converter_evdev.h
@@ -29,7 +29,7 @@ base::FilePath path, int id, InputDeviceType type, - const EventDispatchCallback& dispatch); + const TouchEventDispatchCallback& touch_callback); ~TouchEventConverterEvdev() override; // EventConverterEvdev: @@ -70,7 +70,7 @@ void ReportEvents(base::TimeDelta delta); // Callback for dispatching events. - EventDispatchCallback callback_; + TouchEventDispatchCallback touch_callback_; // Set if we have seen a SYN_DROPPED and not yet re-synced with the device. bool syn_dropped_;
diff --git a/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc b/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc index 3ef699d..3a48c2f 100644 --- a/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc +++ b/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc
@@ -17,7 +17,6 @@ #include "base/time/time.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/events/devices/device_data_manager.h" -#include "ui/events/event.h" #include "ui/events/ozone/evdev/touch_event_converter_evdev.h" #include "ui/events/platform/platform_event_dispatcher.h" #include "ui/events/platform/platform_event_source.h" @@ -47,11 +46,9 @@ long queue_index); unsigned size() { return dispatched_events_.size(); } - TouchEvent* event(unsigned index) { + const TouchEventParams& event(unsigned index) { DCHECK_GT(dispatched_events_.size(), index); - Event* ev = dispatched_events_[index]; - DCHECK(ev->IsTouchEvent()); - return static_cast<TouchEvent*>(ev); + return dispatched_events_[index]; } // Actually dispatch the event reader code. @@ -60,8 +57,8 @@ base::RunLoop().RunUntilIdle(); } - void DispatchCallback(scoped_ptr<Event> event) { - dispatched_events_.push_back(event.release()); + void DispatchCallback(const TouchEventParams& params) { + dispatched_events_.push_back(params); } void Initialize(const EventDeviceInfo& device_info) override {} @@ -71,7 +68,7 @@ int read_pipe_; int write_pipe_; - ScopedVector<Event> dispatched_events_; + std::vector<TouchEventParams> dispatched_events_; DISALLOW_COPY_AND_ASSIGN(MockTouchEventConverterEvdev); }; @@ -185,17 +182,15 @@ dev->ReadNow(); EXPECT_EQ(1u, dev->size()); - ui::TouchEvent* event = dev->event(0); - EXPECT_FALSE(event == NULL); + ui::TouchEventParams event = dev->event(0); - EXPECT_EQ(ui::ET_TOUCH_PRESSED, event->type()); - EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), event->time_stamp()); - EXPECT_EQ(42, event->x()); - EXPECT_EQ(51, event->y()); - EXPECT_EQ(0, event->touch_id()); - EXPECT_FLOAT_EQ(1.5f, event->radius_x()); - EXPECT_FLOAT_EQ(.5f, event->force()); - EXPECT_FLOAT_EQ(0.f, event->rotation_angle()); + EXPECT_EQ(ui::ET_TOUCH_PRESSED, event.type); + EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), event.timestamp); + EXPECT_EQ(42, event.location.x()); + EXPECT_EQ(51, event.location.y()); + EXPECT_EQ(0, event.touch_id); + EXPECT_FLOAT_EQ(1.5f, event.radii.x()); + EXPECT_FLOAT_EQ(.5f, event.pressure); } TEST_F(TouchEventConverterEvdevTest, NoEvents) { @@ -233,30 +228,26 @@ dev->ConfigureReadMock(mock_kernel_queue_move1, 4, 0); dev->ReadNow(); EXPECT_EQ(2u, dev->size()); - ui::TouchEvent* event = dev->event(1); - EXPECT_FALSE(event == NULL); + ui::TouchEventParams event = dev->event(1); - EXPECT_EQ(ui::ET_TOUCH_MOVED, event->type()); - EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), event->time_stamp()); - EXPECT_EQ(42, event->x()); - EXPECT_EQ(43, event->y()); - EXPECT_EQ(0, event->touch_id()); - EXPECT_FLOAT_EQ(2.f / 3.f, event->force()); - EXPECT_FLOAT_EQ(0.f, event->rotation_angle()); + EXPECT_EQ(ui::ET_TOUCH_MOVED, event.type); + EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), event.timestamp); + EXPECT_EQ(42, event.location.x()); + EXPECT_EQ(43, event.location.y()); + EXPECT_EQ(0, event.touch_id); + EXPECT_FLOAT_EQ(2.f / 3.f, event.pressure); dev->ConfigureReadMock(mock_kernel_queue_move2, 2, 0); dev->ReadNow(); EXPECT_EQ(3u, dev->size()); event = dev->event(2); - EXPECT_FALSE(event == NULL); - EXPECT_EQ(ui::ET_TOUCH_MOVED, event->type()); - EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), event->time_stamp()); - EXPECT_EQ(42, event->x()); - EXPECT_EQ(42, event->y()); - EXPECT_EQ(0, event->touch_id()); - EXPECT_FLOAT_EQ(2.f / 3.f, event->force()); - EXPECT_FLOAT_EQ(0.f, event->rotation_angle()); + EXPECT_EQ(ui::ET_TOUCH_MOVED, event.type); + EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), event.timestamp); + EXPECT_EQ(42, event.location.x()); + EXPECT_EQ(42, event.location.y()); + EXPECT_EQ(0, event.touch_id); + EXPECT_FLOAT_EQ(2.f / 3.f, event.pressure); } TEST_F(TouchEventConverterEvdevTest, TouchRelease) { @@ -278,30 +269,24 @@ dev->ConfigureReadMock(mock_kernel_queue_press, 6, 0); dev->ReadNow(); EXPECT_EQ(1u, dev->size()); - ui::TouchEvent* event = dev->event(0); - EXPECT_FALSE(event == NULL); + ui::TouchEventParams event = dev->event(0); dev->ConfigureReadMock(mock_kernel_queue_release, 2, 0); dev->ReadNow(); EXPECT_EQ(2u, dev->size()); event = dev->event(1); - EXPECT_FALSE(event == NULL); - EXPECT_EQ(ui::ET_TOUCH_RELEASED, event->type()); - EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), event->time_stamp()); - EXPECT_EQ(42, event->x()); - EXPECT_EQ(51, event->y()); - EXPECT_EQ(0, event->touch_id()); - EXPECT_FLOAT_EQ(.5f, event->force()); - EXPECT_FLOAT_EQ(0.f, event->rotation_angle()); + EXPECT_EQ(ui::ET_TOUCH_RELEASED, event.type); + EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), event.timestamp); + EXPECT_EQ(42, event.location.x()); + EXPECT_EQ(51, event.location.y()); + EXPECT_EQ(0, event.touch_id); + EXPECT_FLOAT_EQ(.5f, event.pressure); } TEST_F(TouchEventConverterEvdevTest, TwoFingerGesture) { ui::MockTouchEventConverterEvdev* dev = device(); - ui::TouchEvent* ev0; - ui::TouchEvent* ev1; - struct input_event mock_kernel_queue_press0[] = { {{0, 0}, EV_ABS, ABS_MT_TRACKING_ID, 684}, {{0, 0}, EV_ABS, ABS_MT_TOUCH_MAJOR, 3}, @@ -334,26 +319,24 @@ dev->ConfigureReadMock(mock_kernel_queue_move0press1, 9, 0); dev->ReadNow(); EXPECT_EQ(4u, dev->size()); - ev0 = dev->event(2); - ev1 = dev->event(3); + ui::TouchEventParams ev0 = dev->event(2); + ui::TouchEventParams ev1 = dev->event(3); // Move - EXPECT_EQ(ui::ET_TOUCH_MOVED, ev0->type()); - EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev0->time_stamp()); - EXPECT_EQ(40, ev0->x()); - EXPECT_EQ(51, ev0->y()); - EXPECT_EQ(0, ev0->touch_id()); - EXPECT_FLOAT_EQ(.5f, ev0->force()); - EXPECT_FLOAT_EQ(0.f, ev0->rotation_angle()); + EXPECT_EQ(ui::ET_TOUCH_MOVED, ev0.type); + EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev0.timestamp); + EXPECT_EQ(40, ev0.location.x()); + EXPECT_EQ(51, ev0.location.y()); + EXPECT_EQ(0, ev0.touch_id); + EXPECT_FLOAT_EQ(.5f, ev0.pressure); // Press - EXPECT_EQ(ui::ET_TOUCH_PRESSED, ev1->type()); - EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev1->time_stamp()); - EXPECT_EQ(101, ev1->x()); - EXPECT_EQ(102, ev1->y()); - EXPECT_EQ(1, ev1->touch_id()); - EXPECT_FLOAT_EQ(.5f, ev1->force()); - EXPECT_FLOAT_EQ(0.f, ev1->rotation_angle()); + EXPECT_EQ(ui::ET_TOUCH_PRESSED, ev1.type); + EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev1.timestamp); + EXPECT_EQ(101, ev1.location.x()); + EXPECT_EQ(102, ev1.location.y()); + EXPECT_EQ(1, ev1.touch_id); + EXPECT_FLOAT_EQ(.5f, ev1.pressure); // Stationary 0, Moves 1. struct input_event mock_kernel_queue_stationary0_move1[] = { @@ -364,14 +347,13 @@ EXPECT_EQ(5u, dev->size()); ev1 = dev->event(4); - EXPECT_EQ(ui::ET_TOUCH_MOVED, ev1->type()); - EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev1->time_stamp()); - EXPECT_EQ(40, ev1->x()); - EXPECT_EQ(102, ev1->y()); - EXPECT_EQ(1, ev1->touch_id()); + EXPECT_EQ(ui::ET_TOUCH_MOVED, ev1.type); + EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev1.timestamp); + EXPECT_EQ(40, ev1.location.x()); + EXPECT_EQ(102, ev1.location.y()); + EXPECT_EQ(1, ev1.touch_id); - EXPECT_FLOAT_EQ(.5f, ev1->force()); - EXPECT_FLOAT_EQ(0.f, ev1->rotation_angle()); + EXPECT_FLOAT_EQ(.5f, ev1.pressure); // Move 0, stationary 1. struct input_event mock_kernel_queue_move0_stationary1[] = { @@ -383,13 +365,12 @@ EXPECT_EQ(6u, dev->size()); ev0 = dev->event(5); - EXPECT_EQ(ui::ET_TOUCH_MOVED, ev0->type()); - EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev0->time_stamp()); - EXPECT_EQ(39, ev0->x()); - EXPECT_EQ(51, ev0->y()); - EXPECT_EQ(0, ev0->touch_id()); - EXPECT_FLOAT_EQ(.5f, ev0->force()); - EXPECT_FLOAT_EQ(0.f, ev0->rotation_angle()); + EXPECT_EQ(ui::ET_TOUCH_MOVED, ev0.type); + EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev0.timestamp); + EXPECT_EQ(39, ev0.location.x()); + EXPECT_EQ(51, ev0.location.y()); + EXPECT_EQ(0, ev0.touch_id); + EXPECT_FLOAT_EQ(.5f, ev0.pressure); // Release 0, move 1. struct input_event mock_kernel_queue_release0_move1[] = { @@ -402,21 +383,19 @@ ev0 = dev->event(6); ev1 = dev->event(7); - EXPECT_EQ(ui::ET_TOUCH_RELEASED, ev0->type()); - EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev0->time_stamp()); - EXPECT_EQ(39, ev0->x()); - EXPECT_EQ(51, ev0->y()); - EXPECT_EQ(0, ev0->touch_id()); - EXPECT_FLOAT_EQ(.5f, ev0->force()); - EXPECT_FLOAT_EQ(0.f, ev0->rotation_angle()); + EXPECT_EQ(ui::ET_TOUCH_RELEASED, ev0.type); + EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev0.timestamp); + EXPECT_EQ(39, ev0.location.x()); + EXPECT_EQ(51, ev0.location.y()); + EXPECT_EQ(0, ev0.touch_id); + EXPECT_FLOAT_EQ(.5f, ev0.pressure); - EXPECT_EQ(ui::ET_TOUCH_MOVED, ev1->type()); - EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev1->time_stamp()); - EXPECT_EQ(38, ev1->x()); - EXPECT_EQ(102, ev1->y()); - EXPECT_EQ(1, ev1->touch_id()); - EXPECT_FLOAT_EQ(.5f, ev1->force()); - EXPECT_FLOAT_EQ(0.f, ev1->rotation_angle()); + EXPECT_EQ(ui::ET_TOUCH_MOVED, ev1.type); + EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev1.timestamp); + EXPECT_EQ(38, ev1.location.x()); + EXPECT_EQ(102, ev1.location.y()); + EXPECT_EQ(1, ev1.touch_id); + EXPECT_FLOAT_EQ(.5f, ev1.pressure); // Release 1. struct input_event mock_kernel_queue_release1[] = { @@ -427,13 +406,12 @@ EXPECT_EQ(9u, dev->size()); ev1 = dev->event(8); - EXPECT_EQ(ui::ET_TOUCH_RELEASED, ev1->type()); - EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev1->time_stamp()); - EXPECT_EQ(38, ev1->x()); - EXPECT_EQ(102, ev1->y()); - EXPECT_EQ(1, ev1->touch_id()); - EXPECT_FLOAT_EQ(.5f, ev1->force()); - EXPECT_FLOAT_EQ(0.f, ev1->rotation_angle()); + EXPECT_EQ(ui::ET_TOUCH_RELEASED, ev1.type); + EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev1.timestamp); + EXPECT_EQ(38, ev1.location.x()); + EXPECT_EQ(102, ev1.location.y()); + EXPECT_EQ(1, ev1.touch_id); + EXPECT_FLOAT_EQ(.5f, ev1.pressure); } TEST_F(TouchEventConverterEvdevTest, TypeA) { @@ -525,18 +503,18 @@ if (kExpectedEventCount != dev->size()) return; - ui::TouchEvent* ev0 = dev->event(0); - ui::TouchEvent* ev1 = dev->event(1); + ui::TouchEventParams ev0 = dev->event(0); + ui::TouchEventParams ev1 = dev->event(1); - EXPECT_EQ(0, ev0->touch_id()); - EXPECT_EQ(999, ev0->x()); - EXPECT_EQ(888, ev0->y()); - EXPECT_FLOAT_EQ(0.8333333f, ev0->force()); + EXPECT_EQ(0, ev0.touch_id); + EXPECT_EQ(999, ev0.location.x()); + EXPECT_EQ(888, ev0.location.y()); + EXPECT_FLOAT_EQ(0.8333333f, ev0.pressure); - EXPECT_EQ(1, ev1->touch_id()); - EXPECT_EQ(777, ev1->x()); - EXPECT_EQ(666, ev1->y()); - EXPECT_FLOAT_EQ(0.4666666f, ev1->force()); + EXPECT_EQ(1, ev1.touch_id); + EXPECT_EQ(777, ev1.location.x()); + EXPECT_EQ(666, ev1.location.y()); + EXPECT_FLOAT_EQ(0.4666666f, ev1.pressure); } // crbug.com/446939
diff --git a/ui/events/ozone/events_ozone.gyp b/ui/events/ozone/events_ozone.gyp index 2e60a8e..e4368da 100644 --- a/ui/events/ozone/events_ozone.gyp +++ b/ui/events/ozone/events_ozone.gyp
@@ -81,6 +81,8 @@ 'evdev/event_converter_evdev_impl.h', 'evdev/event_device_info.cc', 'evdev/event_device_info.h', + 'evdev/event_dispatch_callback.cc', + 'evdev/event_dispatch_callback.h', 'evdev/event_factory_evdev.cc', 'evdev/event_factory_evdev.h', 'evdev/event_modifiers_evdev.cc',
diff --git a/ui/events/platform/platform_event_source_stub.cc b/ui/events/platform/platform_event_source_stub.cc index 57e2a61..6e3b2cf8 100644 --- a/ui/events/platform/platform_event_source_stub.cc +++ b/ui/events/platform/platform_event_source_stub.cc
@@ -7,7 +7,7 @@ namespace ui { scoped_ptr<PlatformEventSource> PlatformEventSource::CreateDefault() { - return scoped_ptr<PlatformEventSource>(); + return nullptr; } } // namespace ui
diff --git a/ui/events/platform/x11/x11_event_source_libevent.cc b/ui/events/platform/x11/x11_event_source_libevent.cc index 8ad7931b..0df1977 100644 --- a/ui/events/platform/x11/x11_event_source_libevent.cc +++ b/ui/events/platform/x11/x11_event_source_libevent.cc
@@ -22,7 +22,7 @@ AddEventWatcher(); } - virtual ~X11EventSourceLibevent() { + ~X11EventSourceLibevent() override { } private: @@ -39,16 +39,16 @@ } // PlatformEventSource: - virtual void OnDispatcherListChanged() override { + void OnDispatcherListChanged() override { AddEventWatcher(); } // base::MessagePumpLibevent::Watcher: - virtual void OnFileCanReadWithoutBlocking(int fd) override { + void OnFileCanReadWithoutBlocking(int fd) override { DispatchXEvents(); } - virtual void OnFileCanWriteWithoutBlocking(int fd) override { + void OnFileCanWriteWithoutBlocking(int fd) override { NOTREACHED(); }
diff --git a/ui/events/test/test_event_target.cc b/ui/events/test/test_event_target.cc index 1274dd5..dc0e80d 100644 --- a/ui/events/test/test_event_target.cc +++ b/ui/events/test/test_event_target.cc
@@ -37,7 +37,7 @@ c->set_parent(NULL); return scoped_ptr<TestEventTarget>(c); } - return scoped_ptr<TestEventTarget>(); + return nullptr; } void TestEventTarget::SetEventTargeter(scoped_ptr<EventTargeter> targeter) {
diff --git a/ui/events/x/events_x_unittest.cc b/ui/events/x/events_x_unittest.cc index 065e804..fb74424 100644 --- a/ui/events/x/events_x_unittest.cc +++ b/ui/events/x/events_x_unittest.cc
@@ -553,8 +553,7 @@ EXPECT_EQ(ui::ET_KEY_PRESSED, ui::EventTypeFromNative(xev)); device_data_manager->EnableDevice(blocked_device_id); - device_data_manager->SetDisabledKeyboardAllowedKeys( - scoped_ptr<std::set<KeyboardCode> >()); + device_data_manager->SetDisabledKeyboardAllowedKeys(nullptr); // A key returns KEY_PRESSED as per usual now that keyboard was re-enabled. xev.InitGenericKeyEvent(master_device_id,
diff --git a/ui/file_manager/file_manager/background/js/app_window_wrapper.js b/ui/file_manager/file_manager/background/js/app_window_wrapper.js index fea1cd6..f846e140 100644 --- a/ui/file_manager/file_manager/background/js/app_window_wrapper.js +++ b/ui/file_manager/file_manager/background/js/app_window_wrapper.js
@@ -250,9 +250,6 @@ // Remove the window from the set. delete window.background.appWindows[this.id_]; - // If there is no application window, reset window ID. - if (!Object.keys(window.background.appWindows).length) - nextFileManagerWindowID = 0; window.background.tryClose(); };
diff --git a/ui/file_manager/file_manager/background/js/background.js b/ui/file_manager/file_manager/background/js/background.js index 1c5a027..dba32400 100644 --- a/ui/file_manager/file_manager/background/js/background.js +++ b/ui/file_manager/file_manager/background/js/background.js
@@ -79,7 +79,8 @@ */ this.mediaScanner = new importer.DefaultMediaScanner( importer.createMetadataHashcode, - this.historyLoader); + this.historyLoader, + importer.DefaultDirectoryWatcher.create); /** * Handles importing of user media (e.g. photos, videos) from removable
diff --git a/ui/file_manager/file_manager/background/js/import_history.js b/ui/file_manager/file_manager/background/js/import_history.js index d8ac997..39acc35 100644 --- a/ui/file_manager/file_manager/background/js/import_history.js +++ b/ui/file_manager/file_manager/background/js/import_history.js
@@ -36,6 +36,13 @@ importer.ImportHistory.prototype.markCopied; /** + * List urls of all files that are marked as copied, but not marked as synced. + * @param {!importer.Destination} destination + * @return {!Promise.<!Array.<string>>} + */ +importer.ImportHistory.prototype.listUnimportedUrls; + +/** * @param {!FileEntry} entry * @param {!importer.Destination} destination * @return {!Promise.<?>} Resolves when the operation is completed. @@ -118,6 +125,12 @@ }; /** @override */ +importer.DummyImportHistory.prototype.listUnimportedUrls = + function(destination) { + return Promise.resolve([]); +}; + +/** @override */ importer.DummyImportHistory.prototype.markImported = function(entry, destination) { return Promise.resolve(); @@ -467,6 +480,27 @@ }; /** @override */ +importer.PersistentImportHistory.prototype.listUnimportedUrls = + function(destination) { + return this.whenReady_.then( + function() { + // TODO(smckay): Merge copy and sync records for simpler + // unimported file discovery. + var unimported = []; + for (var key in this.copiedEntries_) { + var imported = this.importedEntries_[key]; + for (var destination in this.copiedEntries_[key]) { + if (!imported || imported.indexOf(destination) === -1) { + unimported.push( + this.copiedEntries_[key][destination].destinationUrl); + } + } + } + return unimported; + }.bind(this)); +}; + +/** @override */ importer.PersistentImportHistory.prototype.markImported = function(entry, destination) { return this.whenReady_ @@ -729,13 +763,27 @@ importer.FileEntryRecordStorage = function(fileEntry) { /** @private {!importer.PromisingFileEntry} */ this.fileEntry_ = new importer.PromisingFileEntry(fileEntry); + + /** + * Serializes all writes and reads. + * @private {!Promise.<?>} + * */ + this.latestOperation_ = Promise.resolve(null); }; /** @override */ importer.FileEntryRecordStorage.prototype.write = function(record) { - // TODO(smckay): should we make an effort to reuse a file writer? - return this.fileEntry_.createWriter() - .then(this.writeRecord_.bind(this, record)); + return this.latestOperation_ = this.latestOperation_ + .then( + /** + * @param {?} ignore + * @this {importer.FileEntryRecordStorage} + */ + function(ignore) { + return this.fileEntry_.createWriter(); + }.bind(this)) + .then(this.writeRecord_.bind(this, record)) + .catch(importer.getLogger().catcher('record-writing')); }; /** @@ -768,26 +816,35 @@ /** @override */ importer.FileEntryRecordStorage.prototype.readAll = function() { - return this.fileEntry_.file() - .then( - this.readFileAsText_.bind(this), - /** - * @return {string} - * @this {importer.FileEntryRecordStorage} - */ - function() { - console.error('Unable to read from history file.'); - return ''; - }.bind(this)) - .then( - /** - * @param {string} fileContents - * @this {importer.FileEntryRecordStorage} - */ - function(fileContents) { - return this.parse_(fileContents); - }.bind(this)) - .catch(importer.getLogger().catcher('record-reading')); + return /** @type {!Promise.<!Array.<!Array.<*>>>} */ (this.latestOperation_ = + this.latestOperation_ + .then( + /** + * @param {?} ignore + * @this {importer.FileEntryRecordStorage} + */ + function(ignore) { + return this.fileEntry_.file(); + }.bind(this)) + .then( + this.readFileAsText_.bind(this), + /** + * @return {string} + * @this {importer.FileEntryRecordStorage} + */ + function() { + console.error('Unable to read from history file.'); + return ''; + }.bind(this)) + .then( + /** + * @param {string} fileContents + * @this {importer.FileEntryRecordStorage} + */ + function(fileContents) { + return this.parse_(fileContents); + }.bind(this)) + .catch(importer.getLogger().catcher('record-reading'))); }; /** @@ -864,6 +921,15 @@ this.history_.addObserver( this.onHistoryChanged_.bind(this)); + this.history_.whenReady_ + .then( + function() { + this.history_.listUnimportedUrls(importer.Destination.GOOGLE_DRIVE) + .then(this.updateSyncStatus_.bind( + this, + importer.Destination.GOOGLE_DRIVE)); + }.bind(this)); + // Listener is only registered once the history object is initialized. // No need to register synchonously since we don't want to be // woken up to respond to events. @@ -872,6 +938,29 @@ // TODO(smckay): Listen also for errors on onDriveSyncError. }; +/** @const {number} */ +importer.DriveSyncWatcher.UPDATE_DELAY_MS = 3500; + +/** + * @param {!importer.Destination} destination + * @param {!Array.<string>} unimportedUrls + * @private + */ +importer.DriveSyncWatcher.prototype.updateSyncStatus_ = + function(destination, unimportedUrls) { + // TODO(smckay): Chunk processing of urls...to ensure we're not + // blocking interactive tasks. For now, we just defer the update + // for a few seconds. + setTimeout( + function() { + unimportedUrls.forEach( + function(url) { + this.checkSyncStatus_(destination, url); + }.bind(this)); + }.bind(this), + importer.DriveSyncWatcher.UPDATE_DELAY_MS); +}; + /** * @param {!FileTransferStatus} status * @private @@ -893,34 +982,73 @@ // Check sync status incase the file synced *before* it was able // to mark be marked as copied. this.checkSyncStatus_( - event.entry, event.destination, - event.destinationUrl); + event.destinationUrl, + event.entry); } }; /** - * @param {!FileEntry} entry * @param {!importer.Destination} destination * @param {string} url + * @param {!FileEntry=} opt_entry Pass this if you have an entry + * on hand, else, we'll jump through some extra hoops to + * make do without it. * @private */ importer.DriveSyncWatcher.prototype.checkSyncStatus_ = - function(entry, destination, url) { - // TODO(smckay): User Metadata Cache...once it is available - // in the background. - chrome.fileManagerPrivate.getEntryProperties( - [url], - /** - * @param {!Array.<Object>} propertiesList - * @this {importer.DriveSyncWatcher} - */ - function(propertiesList) { - console.assert(propertiesList.length === 1); - var data = propertiesList[0]; - if (!data['isDirty']) { - this.history_.markImported(entry, destination); - } + function(destination, url, opt_entry) { + console.assert( + destination === importer.Destination.GOOGLE_DRIVE, + 'Unsupported destination: ' + destination); + + this.getSyncStatus_(url) + .then( + /** + * @param {boolean} synced True if file is synced + * @this {importer.DriveSyncWatcher} + */ + function(synced) { + if (synced) { + if (opt_entry) { + this.history_.markImported(opt_entry, destination); + } else { + this.history_.markImportedByUrl(url); + } + } + }.bind(this)); +}; + +/** + * @param {string} url + * @return {!Promise.<boolean>} Resolves with true if the + * file has been synced to the named destination. + * @private + */ +importer.DriveSyncWatcher.prototype.getSyncStatus_ = + function(url) { + return new Promise( + /** @this {importer.DriveSyncWatcher} */ + function(resolve, reject) { + // TODO(smckay): User Metadata Cache...once it is available + // in the background. + chrome.fileManagerPrivate.getEntryProperties( + [url], + /** + * @param {!Array.<Object>} propertiesList + * @this {importer.DriveSyncWatcher} + */ + function(propertiesList) { + console.assert( + propertiesList.length === 1, + 'Got an unexpected number of results.'); + if (chrome.runtime.lastError) { + reject(chrome.runtime.lastError); + } else { + var data = propertiesList[0]; + resolve(!data['isDirty']); + } + }.bind(this)); }.bind(this)); };
diff --git a/ui/file_manager/file_manager/background/js/import_history_unittest.js b/ui/file_manager/file_manager/background/js/import_history_unittest.js index c9b38f2..999963a 100644 --- a/ui/file_manager/file_manager/background/js/import_history_unittest.js +++ b/ui/file_manager/file_manager/background/js/import_history_unittest.js
@@ -67,7 +67,7 @@ // but not for this file. testPromise = historyProvider.then( function(history) { - history.wasCopied(testFileEntry, SPACE_CAMP).then(assertFalse); + return history.wasCopied(testFileEntry, SPACE_CAMP).then(assertFalse); }); reportPromise(testPromise, callback); @@ -77,7 +77,7 @@ // TestRecordWriter is pre-configured with this entry. testPromise = historyProvider.then( function(history) { - history.wasCopied(testFileEntry, GOOGLE_DRIVE).then(assertTrue); + return history.wasCopied(testFileEntry, GOOGLE_DRIVE).then(assertTrue); }); reportPromise(testPromise, callback); @@ -86,9 +86,10 @@ function testHistoryWasImportedTrueForKnownEntrySetAtRuntime(callback) { testPromise = historyProvider.then( function(history) { - history.markImported(testFileEntry, SPACE_CAMP).then( + return history.markImported(testFileEntry, SPACE_CAMP).then( function() { - history.wasImported(testFileEntry, SPACE_CAMP).then(assertTrue); + return history.wasImported(testFileEntry, SPACE_CAMP) + .then(assertTrue); }); }); @@ -99,7 +100,7 @@ // TestRecordWriter is pre-configured with this entry. testPromise = historyProvider.then( function(history) { - history.wasCopied(testFileEntry, GOOGLE_DRIVE).then(assertTrue); + return history.wasCopied(testFileEntry, GOOGLE_DRIVE).then(assertTrue); }); reportPromise(testPromise, callback); @@ -110,9 +111,9 @@ function(history) { var recorder = new TestCallRecorder(); history.addObserver(recorder.callback); - history.markCopied(testFileEntry, SPACE_CAMP, 'url1').then( + return history.markCopied(testFileEntry, SPACE_CAMP, 'url1').then( function() { - Promise.resolve() + return Promise.resolve() .then( function() { recorder.assertCallCount(1); @@ -152,7 +153,7 @@ // but not for this file. testPromise = historyProvider.then( function(history) { - history.wasImported(testFileEntry, SPACE_CAMP).then(assertFalse); + return history.wasImported(testFileEntry, SPACE_CAMP).then(assertFalse); }); reportPromise(testPromise, callback); @@ -162,7 +163,8 @@ // TestRecordWriter is pre-configured with this entry. testPromise = historyProvider.then( function(history) { - history.wasImported(testFileEntry, GOOGLE_DRIVE).then(assertTrue); + return history.wasImported(testFileEntry, GOOGLE_DRIVE) + .then(assertTrue); }); reportPromise(testPromise, callback); @@ -171,9 +173,10 @@ function testHistoryWasImportedTrueForKnownEntrySetAtRuntime(callback) { testPromise = historyProvider.then( function(history) { - history.markImported(testFileEntry, SPACE_CAMP).then( + return history.markImported(testFileEntry, SPACE_CAMP).then( function() { - history.wasImported(testFileEntry, SPACE_CAMP).then(assertTrue); + return history.wasImported(testFileEntry, SPACE_CAMP) + .then(assertTrue); }); }); @@ -185,9 +188,9 @@ function(history) { var recorder = new TestCallRecorder(); history.addObserver(recorder.callback); - history.markImported(testFileEntry, SPACE_CAMP).then( + return history.markImported(testFileEntry, SPACE_CAMP).then( function() { - Promise.resolve() + return Promise.resolve() .then( function() { recorder.assertCallCount(1); @@ -211,9 +214,9 @@ var promises = []; promises.push(history.markCopied(testFileEntry, SPACE_CAMP, 'url2')); promises.push(history.markImported(testFileEntry, SPACE_CAMP)); - Promise.all(promises).then( + return Promise.all(promises).then( function() { - Promise.resolve() + return Promise.resolve() .then( function() { recorder.assertCallCount(0); @@ -228,14 +231,35 @@ testPromise = createRealStorage('recordStorageTest.data') .then( function(storage) { - storage.write(['abc', '123']).then( + return storage.write(['abc', '123']).then( function() { - storage.readAll().then( + return storage.readAll().then( function(records) { - assertTrue(records.length != 1); + assertEquals(1, records.length); }); }); - }); + }); + + reportPromise(testPromise, callback); +} + +function testRecordStorageSerializingOperations(callback) { + testPromise = createRealStorage('recordStorageTestForSerializing.data') + .then( + function(storage) { + var writePromises = []; + var WRITES_COUNT = 20; + for (var i = 0; i < WRITES_COUNT; i++) + writePromises.push(storage.write(['abc', '123'])); + var readAllPromise = storage.readAll().then( + function(records) { + assertEquals(WRITES_COUNT, records.length); + }); + // Write an extra record, which must be executed afte reading is + // completed. + writePromises.push(storage.write(['abc', '123'])); + return Promise.all(writePromises.concat([readAllPromise])); + }); reportPromise(testPromise, callback); }
diff --git a/ui/file_manager/file_manager/background/js/media_scanner.js b/ui/file_manager/file_manager/background/js/media_scanner.js index 2d4ce96..895c7fa 100644 --- a/ui/file_manager/file_manager/background/js/media_scanner.js +++ b/ui/file_manager/file_manager/background/js/media_scanner.js
@@ -45,6 +45,11 @@ importer.ScanResult.prototype.isFinal; /** + * @return {boolean} true if scanning is invalidated. + */ +importer.ScanResult.prototype.isInvalidated; + +/** * Returns all files entries discovered so far. The list will be * complete only after scanning has completed and {@code isFinal} * returns {@code true}. @@ -85,12 +90,14 @@ * * @param {function(!FileEntry): !Promise.<string>} hashGenerator * @param {!importer.HistoryLoader} historyLoader + * @param {!importer.DirectoryWatcherFactory} watcherFactory */ -importer.DefaultMediaScanner = function(hashGenerator, historyLoader) { +importer.DefaultMediaScanner = function( + hashGenerator, historyLoader, watcherFactory) { /** * A little factory for DefaultScanResults which allows us to forgo * the saving it's dependencies in our fields. - * @private {function(): !importer.DefaultScanResult} + * @return {!importer.DefaultScanResult} */ this.createScanResult_ = function() { return new importer.DefaultScanResult(hashGenerator, historyLoader); @@ -98,6 +105,12 @@ /** @private {!Array.<!importer.ScanObserver>} */ this.observers_ = []; + + /** + * @private {!importer.DirectoryWatcherFactory} + * @const + */ + this.watcherFactory_ = watcherFactory; }; /** @override */ @@ -122,7 +135,16 @@ } var scanResult = this.createScanResult_(); - var scanPromises = entries.map(this.scanEntry_.bind(this, scanResult)); + var watcher = this.watcherFactory_(function() { + scanResult.invalidateScan(); + this.observers_.forEach( + /** @param {!importer.ScanObserver} observer */ + function(observer) { + observer(importer.ScanEvent.INVALIDATED, scanResult); + }); + }.bind(this)); + var scanPromises = entries.map( + this.scanEntry_.bind(this, scanResult, watcher)); Promise.all(scanPromises) .then(scanResult.resolveScan.bind(scanResult)) @@ -155,45 +177,50 @@ * Resolves the entry to a list of {@code FileEntry}. * * @param {!importer.DefaultScanResult} result + * @param {!importer.DirectoryWatcher} watcher * @param {!Entry} entry * @return {!Promise} * @private */ importer.DefaultMediaScanner.prototype.scanEntry_ = - function(result, entry) { + function(result, watcher, entry) { return entry.isFile ? result.onFileEntryFound(/** @type {!FileEntry} */ (entry)) : - this.scanDirectory_(result, /** @type {!DirectoryEntry} */ (entry)); + this.scanDirectory_( + result, watcher, /** @type {!DirectoryEntry} */ (entry)); }; /** * Finds all files beneath directory. * * @param {!importer.DefaultScanResult} result + * @param {!importer.DirectoryWatcher} watcher * @param {!DirectoryEntry} entry * @return {!Promise} * @private */ importer.DefaultMediaScanner.prototype.scanDirectory_ = - function(result, entry) { - return new Promise( - function(resolve, reject) { - // Collect promises for all files being added to results. - // The directory scan promise can't resolve until all - // file entries are completely promised. - var promises = []; - fileOperationUtil.findFilesRecursively( - entry, - /** @param {!FileEntry} fileEntry */ - function(fileEntry) { - promises.push(result.onFileEntryFound(fileEntry)); - }) - .then( - /** @this {importer.DefaultScanResult} */ - function() { - Promise.all(promises).then(resolve).catch(reject); - }); - }); + function(result, watcher, entry) { + // Collect promises for all files being added to results. + // The directory scan promise can't resolve until all + // file entries are completely promised. + var promises = []; + + return fileOperationUtil.findEntriesRecursively( + entry, + /** @param {!Entry} entry */ + function(entry) { + if (watcher.triggered) { + return; + } + if (entry.isDirectory) { + watcher.addDirectory(/** @type {!DirectoryEntry} */(entry)); + } else { + promises.push( + result.onFileEntryFound(/** @type {!FileEntry} */(entry))); + } + }) + .then(Promise.all.bind(Promise, promises)); }; /** @@ -225,6 +252,11 @@ this.fileEntries_ = []; /** + * @private {boolean} + */ + this.invalidated_ = false; + + /** * Hashcodes of all files included captured by this result object so-far. * Used to dedupe newly discovered files against other files withing * the ScanResult. @@ -276,6 +308,10 @@ return this.settled_; }; +importer.DefaultScanResult.prototype.isInvalidated = function() { + return this.invalidated_; +}; + /** @override */ importer.DefaultScanResult.prototype.getFileEntries = function() { return this.fileEntries_; @@ -297,6 +333,13 @@ }; /** + * Invalidates this scan. + */ +importer.DefaultScanResult.prototype.invalidateScan = function() { + this.invalidated_ = true; +}; + +/** * Handles files discovered during scanning. * * @param {!FileEntry} entry @@ -385,3 +428,80 @@ }.bind(this)); }; +/** + * Watcher for directories. + * @interface + */ +importer.DirectoryWatcher = function() {}; + +/** + * Registers new directory to be watched. + * @param {!DirectoryEntry} entry + */ +importer.DirectoryWatcher.prototype.addDirectory = function(entry) {}; + +/** + * @typedef {function()} + */ +importer.DirectoryWatcherFactoryCallback; + +/** + * @typedef {function(importer.DirectoryWatcherFactoryCallback): + * !importer.DirectoryWatcher} + */ +importer.DirectoryWatcherFactory; + +/** + * Watcher for directories. + * @param {function()} callback Callback to be invoked when one of watched + * directories is changed. + * @implements {importer.DirectoryWatcher} + * @constructor + */ +importer.DefaultDirectoryWatcher = function(callback) { + this.callback_ = callback; + this.watchedDirectories_ = {}; + this.triggered = false; + this.listener_ = null; +}; + +/** + * Creates new directory watcher. + * @param {function()} callback Callback to be invoked when one of watched + * directories is changed. + * @return {!importer.DirectoryWatcher} + */ +importer.DefaultDirectoryWatcher.create = function(callback) { + return new importer.DefaultDirectoryWatcher(callback); +}; + +/** + * Registers new directory to be watched. + * @param {!DirectoryEntry} entry + */ +importer.DefaultDirectoryWatcher.prototype.addDirectory = function(entry) { + if (!this.listener_) { + this.listener_ = this.onWatchedDirectoryModified_.bind(this); + chrome.fileManagerPrivate.onDirectoryChanged.addListener( + assert(this.listener_)); + } + this.watchedDirectories_[entry.toURL()] = true; + chrome.fileManagerPrivate.addFileWatch(entry.toURL(), function() {}); +}; + +/** + * @param {FileWatchEvent} event + * @private + */ +importer.DefaultDirectoryWatcher.prototype.onWatchedDirectoryModified_ = + function(event) { + if (!this.watchedDirectories_[event.entry.toURL()]) + return; + this.triggered = true; + for (var url in this.watchedDirectories_) { + chrome.fileManagerPrivate.removeFileWatch(url, function() {}); + } + chrome.fileManagerPrivate.onDirectoryChanged.removeListener( + assert(this.listener_)); + this.callback_(); +};
diff --git a/ui/file_manager/file_manager/background/js/media_scanner_unittest.html b/ui/file_manager/file_manager/background/js/media_scanner_unittest.html index b6cf9ca..53b60e73 100644 --- a/ui/file_manager/file_manager/background/js/media_scanner_unittest.html +++ b/ui/file_manager/file_manager/background/js/media_scanner_unittest.html
@@ -12,16 +12,17 @@ <script src="../../../../../ui/webui/resources/js/load_time_data.js"></script> <script src="../../common/js/volume_manager_common.js"></script> -<script src="../../common/js/importer_common.js"></script> <script src="../../common/js/file_type.js"></script> +<script src="../../common/js/importer_common.js"></script> <script src="../../common/js/mock_entry.js"></script> <script src="../../common/js/mock_file_system.js"></script> <script src="../../common/js/unittest_util.js"></script> <script src="../../common/js/util.js"></script> <script src="file_operation_util.js"></script> <script src="import_history.js"></script> -<script src="test_import_history.js"></script> <script src="media_scanner.js"></script> +<script src="mock_media_scanner.js"></script> +<script src="test_import_history.js"></script> <script src="media_scanner_unittest.js"></script>
diff --git a/ui/file_manager/file_manager/background/js/media_scanner_unittest.js b/ui/file_manager/file_manager/background/js/media_scanner_unittest.js index fbe3df09e..77fe1c1 100644 --- a/ui/file_manager/file_manager/background/js/media_scanner_unittest.js +++ b/ui/file_manager/file_manager/background/js/media_scanner_unittest.js
@@ -17,6 +17,9 @@ /** @type {!importer.TestImportHistory} */ var importHistory; +/** @type {!importer.TestDirectoryWatcher} */ +var watcher; + // Set up the test components. function setUp() { @@ -26,7 +29,11 @@ function(entry) { return Promise.resolve(entry.name); }, - importHistory); + importHistory, + function(callback) { + watcher = new TestDirectoryWatcher(callback); + return watcher; + }); } /** @@ -311,6 +318,25 @@ callback); } +function testInvalidation(callback) { + var invalidatePromise = new Promise(function(fulfill) { + scanner.addObserver(fulfill); + }); + reportPromise( + makeTestFileSystemRoot('testInvalidation') + .then(populateDir.bind(null, ['DCIM'])) + .then( + /** + * Scans the directories. + * @param {!DirectoryEntry} root + */ + function(root) { + scan = scanner.scan([root]); + watcher.callback(); + return invalidatePromise; + }), + callback); +} /** * Verifies the results of the media scan are as expected.
diff --git a/ui/file_manager/file_manager/background/js/mock_media_scanner.js b/ui/file_manager/file_manager/background/js/mock_media_scanner.js index 38659959..59f21e9 100644 --- a/ui/file_manager/file_manager/background/js/mock_media_scanner.js +++ b/ui/file_manager/file_manager/background/js/mock_media_scanner.js
@@ -154,3 +154,31 @@ TestScanResult.prototype.isFinal = function() { return this.settled_; }; + +/** @override */ +TestScanResult.prototype.isInvalidated = function() { + return false; +}; + +/** + * @constructor + * @implements {importer.DirectoryWatcher} + */ +function TestDirectoryWatcher(callback) { + /** + * @public {function()} + * @const + */ + this.callback = callback; + + /** + * @public {boolean} + */ + this.triggered = false; +}; + +/** + * @override + */ +TestDirectoryWatcher.prototype.addDirectory = function() { +};
diff --git a/ui/file_manager/file_manager/background/js/test_import_history.js b/ui/file_manager/file_manager/background/js/test_import_history.js index 56ca5fd..4903ff0 100644 --- a/ui/file_manager/file_manager/background/js/test_import_history.js +++ b/ui/file_manager/file_manager/background/js/test_import_history.js
@@ -107,6 +107,12 @@ return Promise.resolve(); }; +/** @override */ +importer.TestImportHistory.prototype.listUnimportedUrls = + function(destination) { + return Promise.resolve([]); +}; + /** * @param {!FileEntry} entry * @param {!importer.Destination} destination
diff --git a/ui/file_manager/file_manager/common/js/importer_common.js b/ui/file_manager/file_manager/common/js/importer_common.js index f2d9b3a..bd2cd25 100644 --- a/ui/file_manager/file_manager/common/js/importer_common.js +++ b/ui/file_manager/file_manager/common/js/importer_common.js
@@ -7,7 +7,8 @@ /** @enum {string} */ importer.ScanEvent = { - FINALIZED: 'finalized' + FINALIZED: 'finalized', + INVALIDATED: 'invalidated' }; /** @@ -44,7 +45,19 @@ return !!entry && entry.isFile && FileType.isImageOrVideo(entry) && - entry.fullPath.toUpperCase().indexOf('/DCIM/') === 0; + importer.isBeneathMediaDir(entry); +}; + +/** + * Returns true if the entry is a media file (and a descendant of a DCIM dir). + * + * @param {Entry} entry + * @return {boolean} + */ +importer.isBeneathMediaDir = function(entry) { + var path = entry.fullPath.toUpperCase(); + return path.indexOf('/DCIM/') === 0 || + path.indexOf('/MISSINGNO/') >= 0; }; /** @@ -68,8 +81,13 @@ importer.isEligibleEntry = function(volumeInfoProvider, entry) { console.assert(volumeInfoProvider !== null); if (importer.isMediaEntry(entry)) { - var volumeInfo = volumeInfoProvider.getVolumeInfo(entry); - return importer.isEligibleVolume(volumeInfo); + // MissingNo knows no bounds....like volume type checks. + if (entry.fullPath.toUpperCase().indexOf('/MISSINGNO/') >= 0) { + return true; + } else { + var volumeInfo = volumeInfoProvider.getVolumeInfo(entry); + return importer.isEligibleVolume(volumeInfo); + } } return false; }; @@ -87,8 +105,10 @@ return false; } - var fullPath = entry.fullPath.toUpperCase(); - if (fullPath !== '/DCIM' && fullPath !== '/DCIM/') { + var path = entry.fullPath.toUpperCase(); + if (path.indexOf('/MISSINGNO') !== -1) { + return true; + } else if (path !== '/DCIM' && path !== '/DCIM/') { return false; }
diff --git a/ui/file_manager/file_manager/foreground/css/file_manager.css b/ui/file_manager/file_manager/foreground/css/file_manager.css index e66ac842..15cd5792 100644 --- a/ui/file_manager/file_manager/foreground/css/file_manager.css +++ b/ui/file_manager/file_manager/foreground/css/file_manager.css
@@ -11,7 +11,6 @@ * - 525: spinner * - 550: autocomplete-suggestions * - 600: menus - * - 600: tooltip * - 1000: preview thumbnail popup * - 1000: overlay panel (ie. image editor) */ @@ -300,46 +299,72 @@ /* Breadcrumbs and things under the title but above the list view. */ .dialog-header { align-items: center; + background: rgb(27, 168, 243); + color: white; display: flex; flex: none; flex-direction: row; height: 48px; margin: 0; - transition: all 180ms ease; -} - -.dialog-header .volume-icon { - -webkit-margin-start: 10px; - background-position: center center; - background-repeat: no-repeat; - flex: none; - height: 24px; - width: 24px; } .dialog-header > .spacer { flex: auto; } -/* Search box */ +.dialog-header button, +.dialog-header paper-button { + height: 32px; + margin-right: 4px; + min-width: 32px; + width: 32px; +} +.dialog-header button, +.dialog-header button:hover { + color: white; +} + +.dialog-header button > core-icon, +.dialog-header paper-button > core-icon { + height: 16px; + width: 16px; +} + +.dialog-header paper-button::shadow > .button-content { + padding: 8px; +} + +#gear-button { + -webkit-app-region: no-drag; + -webkit-margin-end: 10px; + background-color: transparent; + background-image: none; + background-position: center; + background-repeat: no-repeat; + border: 0; + box-shadow: none; + display: block; + height: 32px; + min-width: 0; + outline: none; + padding: 0; + width: 32px; +} + +#gear-button > core-icon { + margin: 8px; +} + +/* Search box */ #search-box { display: flex; flex: none; } #search-box input { - background-color: #fff; - border-style: none; - color: #333; cursor: default; - display: block; - height: 48px; - line-height: 1em; - margin: 0; - max-width: 100%; - outline: none; - padding: 0; + display: inline-block; transition: width 0.2s ease; width: 0; } @@ -348,6 +373,22 @@ -webkit-appearance: none; } +#search-box paper-input-decorator { + margin-top: -4px; +} + +#search-box paper-input-decorator /deep/ ::-webkit-input-placeholder { + color: rgba(255, 255, 255, 0.5); +} + +#search-box paper-input-decorator /deep/ .unfocused-underline { + background-color: rgba(255, 255, 255, 0.3); +} + +#search-box paper-input-decorator /deep/ .focused-underline { + background-color: rgba(255, 255, 255, 0.5); +} + #search-box.has-cursor input, #search-box.has-text input { width: 176px; @@ -393,28 +434,6 @@ url(../images/files/ui/2x/search_clear_pressed.png) 2x); } -.topbutton-bar { - flex: none; -} - -.topbutton-bar .search-button { - background-image: -webkit-image-set( - url(../images/files/ui/search_icon_active.png) 1x, - url(../images/files/ui/2x/search_icon_active.png) 2x); -} - -.topbutton-bar .view-button.table { - background-image: -webkit-image-set( - url(../images/files/ui/button_list_view.png) 1x, - url(../images/files/ui/2x/button_list_view.png) 2x); -} - -.topbutton-bar .view-button.grid { - background-image: -webkit-image-set( - url(../images/files/ui/button_mosaic_view.png) 1x, - url(../images/files/ui/2x/button_mosaic_view.png) 2x); -} - /* Container for the detail and thumbnail list views. */ .dialog-body { -webkit-transition: all 180ms ease; @@ -477,6 +496,7 @@ flex: auto; flex-direction: row; line-height: 20px; + margin-left: 16px; overflow: hidden; padding-top: 1px; } @@ -491,7 +511,6 @@ /* A single directory name in the list of path breadcrumbs. */ .breadcrumb-path { - color: #141414; cursor: pointer; flex: none; overflow: hidden; @@ -500,23 +519,14 @@ } /* The final breadcrumb, representing the current directory. */ -#search-breadcrumbs .breadcrumb-path.breadcrumb-last { - color: #141414; +.breadcrumb-path.breadcrumb-last { cursor: default; } /* The > arrow between breadcrumbs. */ - .breadcrumbs .separator { - background-image: -webkit-image-set( - url(../images/files/ui/breadcrumb-separator.png) 1x, - url(../images/files/ui/2x/breadcrumb-separator.png) 2x); - background-position: center center; - background-repeat: no-repeat; - flex: none; - height: 10px; - overflow: hidden; - width: 25px; + height: 16px; + width: 16px; } html[dir='rtl'] .breadcrumbs .separator { @@ -1354,73 +1364,6 @@ position: relative; } -.buttonbar .tooltip, -.topbutton-bar .tooltip { - right: -12px; - top: 35px; -} - -/* Tooltips */ -.tooltip { - background: #2d2d2d; - border-radius: 0; - box-shadow: 1px 2px 4px #ccc; - box-sizing: border-box; - color: white; - display: block; - font-size: 11px; - font-weight: bold; - height: 29px; - line-height: 29px; - margin-left: -20px; - min-width: 50px; - opacity: 0; - outline: 1px solid rgba(255, 255, 255, 0.5); - padding: 0 10px; - pointer-events: none; - position: absolute; - text-align: center; - top: 5px; - white-space: nowrap; - z-index: 600; /* Must be below the overlay pane (1000). */ -} - -.tooltip::after, -.tooltip::before { - border-left: 5px solid transparent; - border-right: 5px solid transparent; - border-top: transparent; - content: ''; - display: block; - margin-left: -5px; - position: absolute; - right: 24px; - top: -5px; -} - -.tooltip::after { - border-bottom: 5px solid #2d2d2d; -} - -.tooltip::before { - border-bottom: 5px solid rgba(255, 255, 255, 0.5); -} - -/* Show with delay, disappear instantly */ -@-webkit-keyframes tooltip-show { - 0% { opacity: 0; } - 90% { opacity: 0; } - 100% { opacity: 1; } -} - -:hover > .tooltip { - -webkit-animation-duration: 800ms; - -webkit-animation-iteration-count: 1; - -webkit-animation-name: tooltip-show; - -webkit-animation-timing-function: linear; - opacity: 1; -} - #no-search-results { bottom: 0; display: none; @@ -1483,7 +1426,7 @@ box-sizing: border-box; /* To match the width with the search box's. */ color: rgb(34, 34, 34); flex: none; - margin-top: -7px; + margin-top: 10px; overflow: hidden; padding: 5px 0; position: fixed;
diff --git a/ui/file_manager/file_manager/foreground/images/files/ui/2x/breadcrumb-separator.png b/ui/file_manager/file_manager/foreground/images/files/ui/2x/breadcrumb-separator.png deleted file mode 100644 index bbbfbffc..0000000 --- a/ui/file_manager/file_manager/foreground/images/files/ui/2x/breadcrumb-separator.png +++ /dev/null Binary files differ
diff --git a/ui/file_manager/file_manager/foreground/images/files/ui/2x/button_list_view.png b/ui/file_manager/file_manager/foreground/images/files/ui/2x/button_list_view.png deleted file mode 100644 index 09aa2fd..0000000 --- a/ui/file_manager/file_manager/foreground/images/files/ui/2x/button_list_view.png +++ /dev/null Binary files differ
diff --git a/ui/file_manager/file_manager/foreground/images/files/ui/2x/button_mosaic_view.png b/ui/file_manager/file_manager/foreground/images/files/ui/2x/button_mosaic_view.png deleted file mode 100644 index 1961e46e..0000000 --- a/ui/file_manager/file_manager/foreground/images/files/ui/2x/button_mosaic_view.png +++ /dev/null Binary files differ
diff --git a/ui/file_manager/file_manager/foreground/images/files/ui/breadcrumb-separator.png b/ui/file_manager/file_manager/foreground/images/files/ui/breadcrumb-separator.png deleted file mode 100644 index ed941270..0000000 --- a/ui/file_manager/file_manager/foreground/images/files/ui/breadcrumb-separator.png +++ /dev/null Binary files differ
diff --git a/ui/file_manager/file_manager/foreground/images/files/ui/button_list_view.png b/ui/file_manager/file_manager/foreground/images/files/ui/button_list_view.png deleted file mode 100644 index c553781..0000000 --- a/ui/file_manager/file_manager/foreground/images/files/ui/button_list_view.png +++ /dev/null Binary files differ
diff --git a/ui/file_manager/file_manager/foreground/images/files/ui/button_mosaic_view.png b/ui/file_manager/file_manager/foreground/images/files/ui/button_mosaic_view.png deleted file mode 100644 index 5690834..0000000 --- a/ui/file_manager/file_manager/foreground/images/files/ui/button_mosaic_view.png +++ /dev/null Binary files differ
diff --git a/ui/file_manager/file_manager/foreground/js/compiled_resources.gyp b/ui/file_manager/file_manager/foreground/js/compiled_resources.gyp index 3f5687bb..cb70b25b 100644 --- a/ui/file_manager/file_manager/foreground/js/compiled_resources.gyp +++ b/ui/file_manager/file_manager/foreground/js/compiled_resources.gyp
@@ -96,12 +96,12 @@ './share_client.js', './task_controller.js', './thumbnail_loader.js', + './ui/banners.js', './ui/conflict_dialog.js', './ui/default_action_dialog.js', './ui/dialog_footer.js', './ui/directory_tree.js', './ui/drag_selector.js', - './ui/drive_banners.js', './ui/error_dialog.js', './ui/file_grid.js', './ui/file_manager_ui.js',
diff --git a/ui/file_manager/file_manager/foreground/js/file_manager.js b/ui/file_manager/file_manager/foreground/js/file_manager.js index 4fc8717f..1e8d3e8 100644 --- a/ui/file_manager/file_manager/foreground/js/file_manager.js +++ b/ui/file_manager/file_manager/foreground/js/file_manager.js
@@ -170,13 +170,6 @@ this.spinnerController_ = null; /** - * Banners in the file list. - * @type {FileListBannerController} - * @private - */ - this.bannersController_ = null; - - /** * Gear menu controller. * @type {GearMenuController} * @private @@ -389,18 +382,6 @@ var self = this; - // Get the 'allowRedeemOffers' preference before launching - // FileListBannerController. - chrome.fileManagerPrivate.getPreferences(function(pref) { - self.bannersController_ = new FileListBannerController( - self.directoryModel_, - self.volumeManager_, - self.document_, - pref.allowRedeemOffers); - self.bannersController_.addEventListener( - 'relayout', self.ui_.relayout.bind(self.ui_)); - }); - var listBeingUpdated = null; this.directoryModel_.addEventListener('begin-update-files', function() { self.ui_.listContainer.currentList.startBatchUpdates(); @@ -455,7 +436,16 @@ this.selectionHandler_.onFileSelectionChanged(); this.ui_.listContainer.endBatchUpdates(); - callback(); + // Get the 'allowRedeemOffers' preference for banners. + chrome.fileManagerPrivate.getPreferences(function(pref) { + this.ui_.initBanners( + new Banners( + this.directoryModel_, + this.volumeManager_, + this.document_, + pref.allowRedeemOffers)); + callback(); + }.bind(this)); }; /** @@ -759,7 +749,6 @@ this.historyLoader_), new LocationLine( queryRequiredElement(dom, '#location-breadcrumbs'), - queryRequiredElement(dom, '#location-volume-icon'), this.metadataCache_, this.volumeManager_));
diff --git a/ui/file_manager/file_manager/foreground/js/import_controller.js b/ui/file_manager/file_manager/foreground/js/import_controller.js index 3602087..b6f99d4 100644 --- a/ui/file_manager/file_manager/foreground/js/import_controller.js +++ b/ui/file_manager/file_manager/foreground/js/import_controller.js
@@ -59,8 +59,12 @@ */ this.cachedScans_ = {}; - this.scanner_.addObserver(this.onScanEvent_.bind(this)); - + var listener = this.onScanEvent_.bind(this); + this.scanner_.addObserver(listener); + // Remove the observer when the foreground window is closed. + window.addEventListener('pagehide', function() { + this.scanner_.removeObserver(listener); + }.bind(this)); this.environment_.addVolumeUnmountListener( this.onVolumeUnmounted_.bind(this)); }; @@ -72,8 +76,17 @@ * @private */ importer.ImportController.prototype.onScanEvent_ = function(event, result) { - // TODO(smckay): only do this if this is a directory scan. - if (event === importer.ScanEvent.FINALIZED) { + if (event === importer.ScanEvent.INVALIDATED) { + for (var key in this.cachedScans_) { + for (var url in this.cachedScans_[key]) { + if (this.cachedScans_[key][url].isInvalidated()) { + delete this.cachedScans_[key][url]; + } + } + } + } + if (event === importer.ScanEvent.FINALIZED || + event === importer.ScanEvent.INVALIDATED) { this.updateCommands_(); } }; @@ -104,7 +117,6 @@ * @return {!importer.CommandUpdate} response */ importer.ImportController.prototype.getCommandUpdate = function() { - // If there is no Google Drive mount, Drive may be disabled // or the machine may be running in guest mode. if (this.environment_.isGoogleDriveMounted()) { @@ -240,6 +252,7 @@ scan = this.scanner_.scan([directory]); this.cachedScans_[volumeId][url] = scan; } + assert(!scan.isInvalidated()); return scan; };
diff --git a/ui/file_manager/file_manager/foreground/js/main_scripts.js b/ui/file_manager/file_manager/foreground/js/main_scripts.js index e40240e..61d581c 100644 --- a/ui/file_manager/file_manager/foreground/js/main_scripts.js +++ b/ui/file_manager/file_manager/foreground/js/main_scripts.js
@@ -112,12 +112,12 @@ //<include src="spinner_controller.js"> //<include src="task_controller.js"> //<include src="thumbnail_loader.js"> +//<include src="ui/banners.js" > //<include src="ui/conflict_dialog.js"> //<include src="ui/default_action_dialog.js"> //<include src="ui/dialog_footer.js"> //<include src="ui/directory_tree.js"> //<include src="ui/drag_selector.js"> -//<include src="ui/drive_banners.js" > //<include src="ui/error_dialog.js"> //<include src="ui/file_grid.js"> //<include src="ui/file_manager_ui.js">
diff --git a/ui/file_manager/file_manager/foreground/js/ui/drive_banners.js b/ui/file_manager/file_manager/foreground/js/ui/banners.js similarity index 91% rename from ui/file_manager/file_manager/foreground/js/ui/drive_banners.js rename to ui/file_manager/file_manager/foreground/js/ui/banners.js index baaedb9..05ffdc2 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/drive_banners.js +++ b/ui/file_manager/file_manager/foreground/js/ui/banners.js
@@ -13,8 +13,7 @@ * @constructor * @extends {cr.EventTarget} */ -function FileListBannerController( - directoryModel, volumeManager, document, showOffers) { +function Banners(directoryModel, volumeManager, document, showOffers) { this.directoryModel_ = directoryModel; this.volumeManager_ = volumeManager; this.document_ = assert(document); @@ -61,9 +60,9 @@ } /** - * FileListBannerController extends cr.EventTarget. + * Banners extends cr.EventTarget. */ -FileListBannerController.prototype.__proto__ = cr.EventTarget.prototype; +Banners.prototype.__proto__ = cr.EventTarget.prototype; /** * Key in localStorage to keep number of times the Drive Welcome @@ -87,7 +86,7 @@ * also before registering them as callbacks. * @private */ -FileListBannerController.prototype.initializeWelcomeBanner_ = function() { +Banners.prototype.initializeWelcomeBanner_ = function() { this.usePromoWelcomeBanner_ = !util.boardIs('x86-mario') && !util.boardIs('x86-zgb') && !util.boardIs('x86-alex'); @@ -98,7 +97,7 @@ * has shown. * @private */ -FileListBannerController.prototype.setWelcomeHeaderCounter_ = function(value) { +Banners.prototype.setWelcomeHeaderCounter_ = function(value) { var values = {}; values[WELCOME_HEADER_COUNTER_KEY] = value; chrome.storage.local.set(values); @@ -108,7 +107,7 @@ * @param {number} value How many times the low space warning has dismissed. * @private */ -FileListBannerController.prototype.setWarningDismissedCounter_ = +Banners.prototype.setWarningDismissedCounter_ = function(value) { var values = {}; values[WARNING_DISMISSED_KEY] = value; @@ -121,7 +120,7 @@ * @param {string} areaName "local" or "sync". * @private */ -FileListBannerController.prototype.onStorageChange_ = function(changes, +Banners.prototype.onStorageChange_ = function(changes, areaName) { if (areaName == 'local' && WELCOME_HEADER_COUNTER_KEY in changes) { this.welcomeHeaderCounter_ = changes[WELCOME_HEADER_COUNTER_KEY].newValue; @@ -135,7 +134,7 @@ * Invoked when the drive connection status is change in the volume manager. * @private */ -FileListBannerController.prototype.onDriveConnectionChanged_ = function() { +Banners.prototype.onDriveConnectionChanged_ = function() { this.maybeShowAuthFailBanner_(); }; @@ -144,7 +143,7 @@ * @param {string} messageId Resource ID of the message. * @private */ -FileListBannerController.prototype.prepareAndShowWelcomeBanner_ = +Banners.prototype.prepareAndShowWelcomeBanner_ = function(type, messageId) { this.showWelcomeBanner_(type); @@ -215,7 +214,7 @@ * showing the warning. * @private */ -FileListBannerController.prototype.showLowDriveSpaceWarning_ = +Banners.prototype.showLowDriveSpaceWarning_ = function(show, opt_sizeStats) { var box = this.document_.querySelector('#volume-space-warning'); @@ -281,7 +280,7 @@ * Closes the Drive Welcome banner. * @private */ -FileListBannerController.prototype.closeWelcomeBanner_ = function() { +Banners.prototype.closeWelcomeBanner_ = function() { this.cleanupWelcomeBanner_(); // Stop showing the welcome banner. this.setWelcomeHeaderCounter_(WELCOME_HEADER_COUNTER_LIMIT); @@ -291,8 +290,7 @@ * Shows or hides the welcome banner for drive. * @private */ -FileListBannerController.prototype.checkSpaceAndMaybeShowWelcomeBanner_ = - function() { +Banners.prototype.checkSpaceAndMaybeShowWelcomeBanner_ = function() { if (!this.isOnCurrentProfileDrive()) { // We are not on the drive file system. Do not show (close) the welcome // banner. @@ -367,7 +365,7 @@ * to be called only from checkSpaceAndMaybeShowWelcomeBanner_. * @private */ -FileListBannerController.prototype.maybeShowWelcomeBanner_ = function() { +Banners.prototype.maybeShowWelcomeBanner_ = function() { if (this.directoryModel_.getFileList().length == 0 && this.welcomeHeaderCounter_ == 0) { // Only show the full page banner if the header banner was never shown. @@ -395,7 +393,7 @@ * @return {boolean} True if current directory is on Drive root of current * profile. */ -FileListBannerController.prototype.isOnCurrentProfileDrive = function() { +Banners.prototype.isOnCurrentProfileDrive = function() { var entry = this.directoryModel_.getCurrentDirEntry(); if (!entry || util.isFakeEntry(entry)) return false; @@ -411,7 +409,7 @@ * @param {string} type 'page'|'head'|'none'. * @private */ -FileListBannerController.prototype.showWelcomeBanner_ = function(type) { +Banners.prototype.showWelcomeBanner_ = function(type) { var container = this.document_.querySelector('.dialog-container'); if (container.getAttribute('drive-welcome') != type) { container.setAttribute('drive-welcome', type); @@ -425,7 +423,7 @@ * @param {Event} event The directory-changed event. * @private */ -FileListBannerController.prototype.onDirectoryChanged_ = function(event) { +Banners.prototype.onDirectoryChanged_ = function(event) { var rootVolume = this.volumeManager_.getVolumeInfo(event.newDirEntry); var previousRootVolume = event.previousDirEntry ? this.volumeManager_.getVolumeInfo(event.previousDirEntry) : null; @@ -464,8 +462,7 @@ * to show low space warning. Otherwise false. * @private */ -FileListBannerController.prototype.isLowSpaceWarningTarget_ = - function(volumeInfo) { +Banners.prototype.isLowSpaceWarningTarget_ = function(volumeInfo) { if (!volumeInfo) return false; return volumeInfo.profile.isCurrentProfile && @@ -478,8 +475,7 @@ * @param {Object} event chrome.fileManagerPrivate.onDirectoryChanged event. * @private */ -FileListBannerController.prototype.privateOnDirectoryChanged_ = function( - event) { +Banners.prototype.privateOnDirectoryChanged_ = function(event) { if (!this.directoryModel_.getCurrentDirEntry()) return; @@ -499,8 +495,7 @@ * @param {VolumeInfo} volume Type of volume, which we are interested in. * @private */ -FileListBannerController.prototype.maybeShowLowSpaceWarning_ = function( - volume) { +Banners.prototype.maybeShowLowSpaceWarning_ = function(volume) { // TODO(kaznacheev): Unify the two low space warning. var threshold = 0; switch (volume.volumeType) { @@ -551,7 +546,7 @@ * removes the Drive Welcome banner. * @private */ -FileListBannerController.prototype.cleanupWelcomeBanner_ = function() { +Banners.prototype.cleanupWelcomeBanner_ = function() { this.showWelcomeBanner_('none'); }; @@ -560,7 +555,7 @@ * @param {number} delay In milliseconds. * @private */ -FileListBannerController.prototype.requestRelayout_ = function(delay) { +Banners.prototype.requestRelayout_ = function(delay) { var self = this; setTimeout(function() { cr.dispatchSimpleEvent(self, 'relayout'); @@ -572,8 +567,7 @@ * @param {boolean} show True if the box need to be shown. * @private */ -FileListBannerController.prototype.showLowDownloadsSpaceWarning_ = - function(show) { +Banners.prototype.showLowDownloadsSpaceWarning_ = function(show) { var box = this.document_.querySelector('.downloads-warning'); if (box.hidden == !show) return; @@ -597,8 +591,7 @@ * Creates contents for the DRIVE unmounted panel. * @private */ -FileListBannerController.prototype.ensureDriveUnmountedPanelInitialized_ = - function() { +Banners.prototype.ensureDriveUnmountedPanelInitialized_ = function() { var panel = this.unmountedPanel_; if (panel.firstElementChild) return; @@ -632,7 +625,7 @@ * @param {Event} event Splice event data on volume info list. * @private */ -FileListBannerController.prototype.onVolumeInfoListSplice_ = function(event) { +Banners.prototype.onVolumeInfoListSplice_ = function(event) { var isDriveVolume = function(volumeInfo) { return volumeInfo.volumeType === VolumeManagerCommon.VolumeType.DRIVE; }; @@ -645,7 +638,7 @@ * Hides it otherwise. The panel shows an error message if it failed. * @private */ -FileListBannerController.prototype.updateDriveUnmountedPanel_ = function() { +Banners.prototype.updateDriveUnmountedPanel_ = function() { var node = this.document_.body; if (this.isOnCurrentProfileDrive()) { var driveVolume = this.volumeManager_.getCurrentProfileVolumeInfo( @@ -672,7 +665,7 @@ * current connection information. * @private */ -FileListBannerController.prototype.maybeShowAuthFailBanner_ = function() { +Banners.prototype.maybeShowAuthFailBanner_ = function() { var connection = this.volumeManager_.getDriveConnectionState(); var showDriveNotReachedMessage = this.isOnCurrentProfileDrive() &&
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_manager_ui.js b/ui/file_manager/file_manager/foreground/js/ui/file_manager_ui.js index 6fb84305..4c62454 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/file_manager_ui.js +++ b/ui/file_manager/file_manager/foreground/js/ui/file_manager_ui.js
@@ -226,6 +226,12 @@ }; /** + * Banners in the file list. + * @type {Banners} + */ + this.banners = null; + + /** * Dialog footer. * @type {!DialogFooter} */ @@ -331,6 +337,15 @@ }; /** + * TODO(mtomasz): Merge the method into initAdditionalUI if possible. + * @param {!Banners} banners + */ +FileManagerUI.prototype.initBanners = function(banners) { + this.banners = banners; + this.banners.addEventListener('relayout', this.relayout.bind(this)); +}; + +/** * Relayouts the UI. */ FileManagerUI.prototype.relayout = function() { @@ -351,15 +366,14 @@ FileManagerUI.prototype.setCurrentListType = function(listType) { this.listContainer.setCurrentListType(listType); + var iconElement = queryRequiredElement(this.toggleViewButton, 'core-icon'); switch (listType) { case ListContainer.ListType.DETAIL: - this.toggleViewButton.classList.remove('table'); - this.toggleViewButton.classList.add('grid'); + iconElement.icon = 'view-module'; break; case ListContainer.ListType.THUMBNAIL: - this.toggleViewButton.classList.remove('grid'); - this.toggleViewButton.classList.add('table'); + iconElement.icon = 'view-list'; break; default:
diff --git a/ui/file_manager/file_manager/foreground/js/ui/location_line.js b/ui/file_manager/file_manager/foreground/js/ui/location_line.js index 9f94dd9..da18cc0 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/location_line.js +++ b/ui/file_manager/file_manager/foreground/js/ui/location_line.js
@@ -7,14 +7,12 @@ * class. * @extends {cr.EventTarget} * @param {!Element} breadcrumbs Container element for breadcrumbs. - * @param {!Element} volumeIcon Volume icon. * @param {!MetadataCache} metadataCache To retrieve metadata. * @param {!VolumeManagerWrapper} volumeManager Volume manager. * @constructor */ -function LocationLine(breadcrumbs, volumeIcon, metadataCache, volumeManager) { +function LocationLine(breadcrumbs, metadataCache, volumeManager) { this.breadcrumbs_ = breadcrumbs; - this.volumeIcon_ = volumeIcon; this.metadataCache_ = metadataCache; this.volumeManager_ = volumeManager; this.entry_ = null; @@ -47,31 +45,6 @@ this.entry_ = entry; this.showSequence_++; - // Clear the background image for the icon and the sub type (if any). - this.volumeIcon_.removeAttribute('style'); - this.volumeIcon_.removeAttribute('volume-subtype'); - - // Updates volume icon. - var locationInfo = this.volumeManager_.getLocationInfo(entry); - if (locationInfo && locationInfo.rootType && locationInfo.isRootEntry) { - if (locationInfo.volumeInfo.volumeType === - VolumeManagerCommon.VolumeType.PROVIDED) { - var extensionId = locationInfo.volumeInfo.extensionId; - var backgroundImage = '-webkit-image-set(' + - 'url(chrome://extension-icon/' + extensionId + '/16/1) 1x, ' + - 'url(chrome://extension-icon/' + extensionId + '/32/1) 2x);'; - this.volumeIcon_.setAttribute( - 'style', 'background-image: ' + backgroundImage); - } - this.volumeIcon_.setAttribute( - 'volume-type-icon', locationInfo.rootType); - } else { - this.volumeIcon_.setAttribute( - 'volume-type-icon', locationInfo.volumeInfo.volumeType); - this.volumeIcon_.setAttribute( - 'volume-subtype', locationInfo.volumeInfo.deviceType || ''); - } - var queue = new AsyncUtil.Queue(); var entries = []; var error = false; @@ -177,7 +150,8 @@ } // Add a separator. - var separator = doc.createElement('div'); + var separator = doc.createElement('core-icon'); + separator.setAttribute('icon', 'chevron-right'); separator.className = 'separator'; this.breadcrumbs_.appendChild(separator); }
diff --git a/ui/file_manager/file_manager/main.html b/ui/file_manager/file_manager/main.html index f01f69e..f6b128b 100644 --- a/ui/file_manager/file_manager/main.html +++ b/ui/file_manager/file_manager/main.html
@@ -15,8 +15,6 @@ <meta name="google" value="notranslate"> <link rel="stylesheet" href="chrome://resources/css/text_defaults.css"> - <link rel="stylesheet" href="chrome://resources/css/apps/topbutton_bar.css"> - <link rel="stylesheet" href="foreground/css/list.css"> <link rel="stylesheet" href="foreground/css/table.css"> <link rel="stylesheet" href="foreground/css/tree.css"> @@ -28,6 +26,13 @@ <link rel="stylesheet" href="foreground/css/file_types.css"> <link rel="stylesheet" href="foreground/css/common.css"> + <link rel="import" href="chrome://resources/polymer/core-icon/core-icon.html"> + <link rel="import" href="chrome://resources/polymer/core-icons/core-icons.html"> + <link rel="import" href="chrome://resources/polymer/core-input/core-input.html"> + <link rel="import" href="chrome://resources/polymer/paper-button/paper-button.html"> + <link rel="import" href="chrome://resources/polymer/paper-input/paper-input-decorator.html"> + <link rel="import" href="chrome://resources/polymer/paper-ripple/paper-ripple.html"> + <!-- Don't load main_scripts.js when flattening is disabled. --> <if expr="False"><!-- </if> <script src="foreground/js/main_scripts.js"></script> @@ -127,12 +132,12 @@ <script src="foreground/js/spinner_controller.js"></script> <script src="foreground/js/task_controller.js"></script> <script src="foreground/js/thumbnail_loader.js"></script> + <script src="foreground/js/ui/banners.js"></script> <script src="foreground/js/ui/conflict_dialog.js"></script> <script src="foreground/js/ui/default_action_dialog.js"></script> <script src="foreground/js/ui/dialog_footer.js"></script> <script src="foreground/js/ui/directory_tree.js"></script> <script src="foreground/js/ui/drag_selector.js"></script> - <script src="foreground/js/ui/drive_banners.js"></script> <script src="foreground/js/ui/error_dialog.js"></script> <script src="foreground/js/ui/file_grid.js"></script> <script src="foreground/js/ui/file_manager_ui.js"></script> @@ -300,6 +305,29 @@ <cr-menu-item command="#delete" i18n-content="DELETE_BUTTON_LABEL"></cr-menu-item> </cr-menu> + <div class="dialog-header"> + <div id="location-breadcrumbs" class="breadcrumbs"></div> + <div class="spacer"></div> + <paper-button id="search-button" tabindex="7"> + <core-icon icon="search"></core-icon> + </paper-button> + <div id="search-box"> + <paper-input-decorator i18n-values="label:SEARCH_TEXT_LABEL"> + <input is="core-input" type="search" tabindex="-1" i18n-values="aria-label:SEARCH_TEXT_LABEL"> + </paper-input-decorator> + <button class="clear" tabindex="-1"></button> + </div> + <paper-button id="view-button" tabindex="8"> + <core-icon icon="view-module"></core-icon> + </paper-button> + <button id="gear-button" tabindex="9" menu="#gear-menu" + i18n-values="aria-label:GEAR_BUTTON_TOOLTIP" + aria-activedescendant="gear-menu"> + <core-icon icon="more-vert"></core-icon> + <paper-ripple fit></paper-ripple> + </button> + </div> + <div class="dialog-container"> <div class="dialog-navigation-list"> <div class="dialog-navigation-list-contents"> @@ -327,25 +355,6 @@ </div> <div class="splitter" id="navigation-list-splitter"></div> <div class="dialog-main"> - <div class="dialog-header"> - <span id="location-volume-icon" class="icon volume-icon"></span> - <div id="location-breadcrumbs" class="breadcrumbs"></div> - <div class="spacer"></div> - <div class="topbutton-bar"> - <button class="menubutton icon search-button" id="search-button" tabindex="7"></button> - <div id="search-box"> - <input type="search" tabindex="-1" - i18n-values="aria-label:SEARCH_TEXT_LABEL;placeholder:SEARCH_TEXT_LABEL"> - <button class="clear" tabindex="-1"></button> - </div> - <button class="menubutton view-button" id="view-button" tabindex="8"></button> - <button class="menubutton gear-button" id="gear-button" tabindex="9" - menu="#gear-menu" - i18n-values="aria-label:GEAR_BUTTON_TOOLTIP" - aria-activedescendant="gear-menu"> - </button> - </div> - </div> <div class="dialog-body"> <div class="main-panel"> <div class="filelist-panel">
diff --git a/ui/file_manager/file_manager/manifest.json b/ui/file_manager/file_manager/manifest.json index 85674c3..177b840a 100644 --- a/ui/file_manager/file_manager/manifest.json +++ b/ui/file_manager/file_manager/manifest.json
@@ -194,6 +194,6 @@ ] }, // chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp is the image loader extension. - "content_security_policy": "default-src 'none'; script-src 'self' chrome://resources chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp; style-src 'self' 'unsafe-inline' chrome://resources; frame-src 'self' about:; img-src 'self' chrome://resources chrome://theme data: https://docs.google.com https://*.googleusercontent.com chrome://extension-icon; media-src 'self' https://*.googleusercontent.com; connect-src https://drive.google.com; object-src 'self'" + "content_security_policy": "default-src 'none'; script-src 'self' chrome://resources chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp; style-src 'self' 'unsafe-inline' chrome://resources; frame-src 'self' about:; img-src 'self' chrome://resources chrome://theme data: https://docs.google.com https://*.googleusercontent.com chrome://extension-icon; media-src 'self' https://*.googleusercontent.com; connect-src https://drive.google.com chrome://resources; object-src 'self'" } }
diff --git a/ui/gfx/image/image_unittest_util.cc b/ui/gfx/image/image_unittest_util.cc index daf2113..daca53f5 100644 --- a/ui/gfx/image/image_unittest_util.cc +++ b/ui/gfx/image/image_unittest_util.cc
@@ -21,6 +21,7 @@ #include "skia/ext/skia_utils_ios.h" #elif defined(OS_MACOSX) #include "base/mac/foundation_util.h" +#include "base/mac/mac_util.h" #include "skia/ext/skia_utils_mac.h" #endif @@ -187,7 +188,8 @@ base::mac::NSObjectRetain(image); return image; #elif defined(OS_MACOSX) - NSImage* image = gfx::SkBitmapToNSImage(bitmap); + NSImage* image = gfx::SkBitmapToNSImageWithColorSpace( + bitmap, base::mac::GetGenericRGBColorSpace()); base::mac::NSObjectRetain(image); return image; #else
diff --git a/ui/gfx/render_text.cc b/ui/gfx/render_text.cc index a95b80f..59742cc 100644 --- a/ui/gfx/render_text.cc +++ b/ui/gfx/render_text.cc
@@ -75,7 +75,8 @@ // the entire font height instead. const int space = display_height - ((internal_leading != 0) ? cap_height : font_height); - const int baseline_shift = space / 2 - internal_leading; + const int baseline_shift = + std::ceil(static_cast<float>(space) / 2) - internal_leading; return baseline + std::max(min_shift, std::min(max_shift, baseline_shift)); }
diff --git a/ui/gfx/render_text_unittest.cc b/ui/gfx/render_text_unittest.cc index c5b0bcd..7baa201 100644 --- a/ui/gfx/render_text_unittest.cc +++ b/ui/gfx/render_text_unittest.cc
@@ -2432,4 +2432,37 @@ } } +// This test validates that the RenderText centering baseline is greater than +// the font list baseline for a valid display rect. +TEST_F(RenderTextTest, CenteringBaselineTest) { + FontList font_list("Arial, 12px"); + const std::vector<Font>& fonts = font_list.GetFonts(); + ASSERT_EQ(1U, fonts.size()); + ASSERT_EQ("arial", + base::StringToLowerASCII(fonts[0].GetActualFontNameForTesting())); + + scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); + render_text->SetDisplayRect(Rect(0, 0, 25, 25)); + render_text->SetFontList(font_list); + EXPECT_GT(render_text->GetBaseline(), font_list.GetBaseline()); +} + +#if defined(OS_WIN) +// This test validates that the RenderText centering baseline for uniscribe +// fonts like Devnagri fonts is greater than the font list baseline for a valid +// display rect. +TEST_F(RenderTextTest, CenteringBaselineTestForUniscribeFonts) { + FontList font_list("Madhav, 12px"); + const std::vector<Font>& fonts = font_list.GetFonts(); + ASSERT_EQ(1U, fonts.size()); + ASSERT_EQ("madhav", + base::StringToLowerASCII(fonts[0].GetActualFontNameForTesting())); + + scoped_ptr<RenderText> render_text(RenderText::CreateInstance()); + render_text->SetDisplayRect(Rect(0, 0, 25, 25)); + render_text->SetFontList(font_list); + EXPECT_GT(render_text->GetBaseline(), font_list.GetBaseline()); +} +#endif + } // namespace gfx
diff --git a/ui/gl/gl_surface_egl.cc b/ui/gl/gl_surface_egl.cc index 1b670e1..02c19e8 100644 --- a/ui/gl/gl_surface_egl.cc +++ b/ui/gl/gl_surface_egl.cc
@@ -366,7 +366,7 @@ } bool NativeViewGLSurfaceEGL::Initialize() { - return Initialize(scoped_ptr<VSyncProvider>()); + return Initialize(nullptr); } bool NativeViewGLSurfaceEGL::Initialize(
diff --git a/ui/gl/gl_surface_glx.cc b/ui/gl/gl_surface_glx.cc index dd3eed9..de888e538 100644 --- a/ui/gl/gl_surface_glx.cc +++ b/ui/gl/gl_surface_glx.cc
@@ -211,7 +211,7 @@ return; TRACE_EVENT_INSTANT0("gpu", "vblank", TRACE_EVENT_SCOPE_THREAD); - now = base::TimeTicks::HighResNow(); + now = base::TimeTicks::Now(); glXMakeCurrent(display_, 0, 0); }
diff --git a/ui/keyboard/webui/DEPS b/ui/keyboard/webui/DEPS index ef8ad28..5f8633a 100644 --- a/ui/keyboard/webui/DEPS +++ b/ui/keyboard/webui/DEPS
@@ -1,3 +1,3 @@ include_rules = [ - "+mojo/public", + "+third_party/mojo/src/mojo/public", ]
diff --git a/ui/keyboard/webui/vk_mojo_handler.h b/ui/keyboard/webui/vk_mojo_handler.h index 8d69d15..750120d 100644 --- a/ui/keyboard/webui/vk_mojo_handler.h +++ b/ui/keyboard/webui/vk_mojo_handler.h
@@ -6,7 +6,7 @@ #define UI_KEYBOARD_WEBUI_VK_MOJO_HANDLER_H_ #include "base/macros.h" -#include "mojo/public/cpp/bindings/binding.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/binding.h" #include "ui/base/ime/input_method_observer.h" #include "ui/keyboard/webui/keyboard.mojom.h"
diff --git a/ui/keyboard/webui/vk_webui_controller.cc b/ui/keyboard/webui/vk_webui_controller.cc index 5fd04ce8..9a4688d 100644 --- a/ui/keyboard/webui/vk_webui_controller.cc +++ b/ui/keyboard/webui/vk_webui_controller.cc
@@ -13,8 +13,8 @@ #include "content/public/common/service_registry.h" #include "grit/keyboard_resources.h" #include "grit/keyboard_resources_map.h" -#include "mojo/public/cpp/bindings/interface_impl.h" -#include "mojo/public/cpp/system/core.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_impl.h" +#include "third_party/mojo/src/mojo/public/cpp/system/core.h" #include "ui/keyboard/keyboard_constants.h" #include "ui/keyboard/keyboard_util.h" #include "ui/keyboard/webui/vk_mojo_handler.h"
diff --git a/ui/keyboard/webui/vk_webui_controller.h b/ui/keyboard/webui/vk_webui_controller.h index 30d1e25..e1b1876f 100644 --- a/ui/keyboard/webui/vk_webui_controller.h +++ b/ui/keyboard/webui/vk_webui_controller.h
@@ -10,8 +10,8 @@ #include "base/memory/weak_ptr.h" #include "content/public/browser/web_ui_controller.h" #include "content/public/browser/web_ui_controller_factory.h" -#include "mojo/public/cpp/bindings/interface_request.h" -#include "mojo/public/cpp/system/core.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h" +#include "third_party/mojo/src/mojo/public/cpp/system/core.h" #include "ui/keyboard/keyboard_export.h" #include "ui/keyboard/webui/keyboard.mojom.h"
diff --git a/ui/login/account_picker/user_pod_row.js b/ui/login/account_picker/user_pod_row.js index 2ad71bd..ec5ce28 100644 --- a/ui/login/account_picker/user_pod_row.js +++ b/ui/login/account_picker/user_pod_row.js
@@ -1033,7 +1033,8 @@ }, customizeUserPodPerUserType: function() { - if (this.user_.supervisedUser && !this.user_.isDesktopUser) { + if ((this.user_.supervisedUser || this.user_.childUser) + && !this.user_.isDesktopUser) { this.setUserPodIconType('supervised'); } else if (this.multiProfilesPolicyApplied) { // Mark user pod as not focusable which in addition to the grayed out
diff --git a/ui/message_center/message_center_impl.cc b/ui/message_center/message_center_impl.cc index 1df3e8fc..cb2f812 100644 --- a/ui/message_center/message_center_impl.cc +++ b/ui/message_center/message_center_impl.cc
@@ -195,8 +195,7 @@ } void ChangeQueue::EraseNotification(const std::string& id, bool by_user) { - scoped_ptr<Change> change( - new Change(CHANGE_TYPE_DELETE, id, scoped_ptr<Notification>())); + scoped_ptr<Change> change(new Change(CHANGE_TYPE_DELETE, id, nullptr)); change->set_by_user(by_user); Replace(id, change.Pass()); }
diff --git a/ui/message_center/views/message_center_view_unittest.cc b/ui/message_center/views/message_center_view_unittest.cc index 8cdf1f7b..273c01e 100644 --- a/ui/message_center/views/message_center_view_unittest.cc +++ b/ui/message_center/views/message_center_view_unittest.cc
@@ -192,7 +192,7 @@ const base::string16& display_source) { // For this test, this method should not be invoked. NOTREACHED(); - return scoped_ptr<ui::MenuModel>(); + return nullptr; } bool MessageCenterViewTest::HasClickedListener(
diff --git a/ui/message_center/views/notification_view_unittest.cc b/ui/message_center/views/notification_view_unittest.cc index 3977f5f..d4c155b 100644 --- a/ui/message_center/views/notification_view_unittest.cc +++ b/ui/message_center/views/notification_view_unittest.cc
@@ -162,7 +162,7 @@ const base::string16& display_source) { // For this test, this method should not be invoked. NOTREACHED(); - return scoped_ptr<ui::MenuModel>(); + return nullptr; } bool NotificationViewTest::HasClickedListener(
diff --git a/ui/message_center/views/notifier_settings_view.cc b/ui/message_center/views/notifier_settings_view.cc index 523545f..21f3fdf 100644 --- a/ui/message_center/views/notifier_settings_view.cc +++ b/ui/message_center/views/notifier_settings_view.cc
@@ -576,7 +576,7 @@ new views::MenuButton(NULL, notifier_group_text, this, true); notifier_group_selector_->SetBorder(scoped_ptr<views::Border>( new views::LabelButtonBorder(views::Button::STYLE_BUTTON)).Pass()); - notifier_group_selector_->SetFocusPainter(scoped_ptr<views::Painter>()); + notifier_group_selector_->SetFocusPainter(nullptr); notifier_group_selector_->set_animate_on_state_change(false); notifier_group_selector_->SetFocusable(true); contents_title_view->AddChildView(notifier_group_selector_);
diff --git a/ui/message_center/views/toast_contents_view.cc b/ui/message_center/views/toast_contents_view.cc index fd753571..bd98d03 100644 --- a/ui/message_center/views/toast_contents_view.cc +++ b/ui/message_center/views/toast_contents_view.cc
@@ -307,7 +307,7 @@ // Should not reach, the context menu should be handled in // MessagePopupCollection. NOTREACHED(); - return scoped_ptr<ui::MenuModel>(); + return nullptr; } bool ToastContentsView::HasClickedListener(
diff --git a/ui/ozone/BUILD.gn b/ui/ozone/BUILD.gn index 543f81c..09041824 100644 --- a/ui/ozone/BUILD.gn +++ b/ui/ozone/BUILD.gn
@@ -171,6 +171,7 @@ test("ozone_unittests") { sources = [ + "common/display_util_unittest.cc", "run_all_unittests.cc", ]
diff --git a/ui/ozone/DEPS b/ui/ozone/DEPS index a0192580..9295171 100644 --- a/ui/ozone/DEPS +++ b/ui/ozone/DEPS
@@ -3,6 +3,7 @@ "+third_party/khronos", "+third_party/skia", "+ui/display/types", + "+ui/display/util", "+ui/events", "+ui/gfx", "+ui/base/cursor",
diff --git a/ui/ozone/common/display_util.cc b/ui/ozone/common/display_util.cc index 432e8580..4ce67c0 100644 --- a/ui/ozone/common/display_util.cc +++ b/ui/ozone/common/display_util.cc
@@ -5,8 +5,12 @@ #include "ui/ozone/common/display_util.h" #include "base/command_line.h" +#include "base/files/file_path.h" +#include "base/files/file_util.h" #include "ui/display/types/display_mode.h" #include "ui/display/types/display_snapshot.h" +#include "ui/display/util/edid_parser.h" +#include "ui/display/util/edid_parser.h" #include "ui/ozone/public/ozone_switches.h" namespace ui { @@ -59,25 +63,19 @@ return params; } -DisplaySnapshot_Params CreateSnapshotFromCommandLine() { - DisplaySnapshot_Params display_param; - +bool CreateSnapshotFromCommandLine(DisplaySnapshot_Params* snapshot_out) { base::CommandLine* cmd = base::CommandLine::ForCurrentProcess(); std::string spec = cmd->GetSwitchValueASCII(switches::kOzoneInitialDisplayBounds); std::string physical_spec = cmd->GetSwitchValueASCII(switches::kOzoneInitialDisplayPhysicalSizeMm); - if (spec.empty()) - return display_param; - int width = 0; int height = 0; - if (sscanf(spec.c_str(), "%dx%d", &width, &height) < 2) - return display_param; - - if (width == 0 || height == 0) - return display_param; + if (spec.empty() || sscanf(spec.c_str(), "%dx%d", &width, &height) < 2 || + width == 0 || height == 0) { + return false; + } int physical_width = 0; int physical_height = 0; @@ -87,16 +85,61 @@ mode_param.size = gfx::Size(width, height); mode_param.refresh_rate = 60; - display_param.display_id = kDummyDisplayId; - display_param.modes.push_back(mode_param); - display_param.type = DISPLAY_CONNECTION_TYPE_INTERNAL; - display_param.physical_size = gfx::Size(physical_width, physical_height); - display_param.has_current_mode = true; - display_param.current_mode = mode_param; - display_param.has_native_mode = true; - display_param.native_mode = mode_param; + snapshot_out->display_id = kDummyDisplayId; + snapshot_out->modes.push_back(mode_param); + snapshot_out->type = DISPLAY_CONNECTION_TYPE_INTERNAL; + snapshot_out->physical_size = gfx::Size(physical_width, physical_height); + snapshot_out->has_current_mode = true; + snapshot_out->current_mode = mode_param; + snapshot_out->has_native_mode = true; + snapshot_out->native_mode = mode_param; + return true; +} - return display_param; +bool CreateSnapshotFromEDID(bool internal, + const std::vector<uint8_t>& edid, + DisplaySnapshot_Params* snapshot_out) { + uint16_t manufacturer_id = 0; + gfx::Size resolution; + + DisplayMode_Params mode_param; + mode_param.refresh_rate = 60.0f; + + if (!ParseOutputDeviceData(edid, &manufacturer_id, + &snapshot_out->display_name, &mode_param.size, + &snapshot_out->physical_size) || + !GetDisplayIdFromEDID(edid, 0, &snapshot_out->display_id)) { + return false; + } + ParseOutputOverscanFlag(edid, &snapshot_out->has_overscan); + + snapshot_out->modes.push_back(mode_param); + // Use VGA for external display for now. + // TODO(oshima): frecon should set this value in the display_info.bin file. + snapshot_out->type = + internal ? DISPLAY_CONNECTION_TYPE_INTERNAL : DISPLAY_CONNECTION_TYPE_VGA; + snapshot_out->has_current_mode = true; + snapshot_out->current_mode = mode_param; + snapshot_out->has_native_mode = true; + snapshot_out->native_mode = mode_param; + return true; +} + +bool CreateSnapshotFromEDIDFile(const base::FilePath& file, + DisplaySnapshot_Params* snapshot_out) { + std::string raw_display_info; + const int kEDIDMaxSize = 128; + if (!base::ReadFileToString(file, &raw_display_info, kEDIDMaxSize + 1) || + raw_display_info.size() < 10) { + return false; + } + std::vector<uint8_t> edid; + // The head of the file contains one byte flag that indicates the type of + // display. + bool internal = raw_display_info[0] == 1; + edid.assign(raw_display_info.c_str() + 1, + raw_display_info.c_str() + raw_display_info.size()); + return CreateSnapshotFromEDID(internal, edid, snapshot_out); } } // namespace ui
diff --git a/ui/ozone/common/display_util.h b/ui/ozone/common/display_util.h index da45b539..898289a9 100644 --- a/ui/ozone/common/display_util.h +++ b/ui/ozone/common/display_util.h
@@ -5,8 +5,14 @@ #ifndef UI_OZONE_COMMON_DISPLAY_UTIL_H_ #define UI_OZONE_COMMON_DISPLAY_UTIL_H_ +#include <vector> + #include "ui/ozone/common/gpu/ozone_gpu_message_params.h" +namespace base { +class FilePath; +} + namespace ui { class DisplayMode; @@ -28,7 +34,19 @@ DisplaySnapshot_Params GetDisplaySnapshotParams(const DisplaySnapshot& display); // Create a display using the Ozone command line parameters. -DisplaySnapshot_Params CreateSnapshotFromCommandLine(); +// Return false if the command line flags are not specified. +bool CreateSnapshotFromCommandLine(DisplaySnapshot_Params* snapshot_out); + +// Create a display snapshot from |file| that contains EDID. +// Return false if the file doesn't exist, or it doesn't contain valid EDID. +bool CreateSnapshotFromEDIDFile(const base::FilePath& file, + DisplaySnapshot_Params* snapshot_out); + +// Create a display snaphot from edid. +// Return false if it doesn't contain valid EDID. +OZONE_EXPORT bool CreateSnapshotFromEDID(bool internal, + const std::vector<uint8_t>& edid, + DisplaySnapshot_Params* snapshot_out); } // namespace ui
diff --git a/ui/ozone/common/display_util_unittest.cc b/ui/ozone/common/display_util_unittest.cc new file mode 100644 index 0000000..39917359 --- /dev/null +++ b/ui/ozone/common/display_util_unittest.cc
@@ -0,0 +1,61 @@ +// Copyright 2015 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 "ui/ozone/common/display_util.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/ozone/common/gpu/ozone_gpu_message_params.h" + +typedef testing::Test DisplayUtilTest; + +namespace ui { +namespace { + +// EDID from HP ZR30w +const unsigned char kTestEDID[] = + "\x00\xff\xff\xff\xff\xff\xff\x00\x22\xf0\x6c\x28\x01\x01\x01\x01" + "\x02\x16\x01\x04\xb5\x40\x28\x78\xe2\x8d\x85\xad\x4f\x35\xb1\x25" + "\x0e\x50\x54\x00\x00\x00\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01" + "\x01\x01\x01\x01\x01\x01\xe2\x68\x00\xa0\xa0\x40\x2e\x60\x30\x20" + "\x36\x00\x81\x90\x21\x00\x00\x1a\xbc\x1b\x00\xa0\x50\x20\x17\x30" + "\x30\x20\x36\x00\x81\x90\x21\x00\x00\x1a\x00\x00\x00\xfc\x00\x48" + "\x50\x20\x5a\x52\x33\x30\x77\x0a\x20\x20\x20\x20\x00\x00\x00\xff" + "\x00\x43\x4e\x34\x32\x30\x32\x31\x33\x37\x51\x0a\x20\x20\x00\x71"; + +} // namespace + +TEST_F(DisplayUtilTest, BasicEDID) { + DisplaySnapshot_Params params; + // -1 to skip NULL byte. + std::vector<uint8_t> edid(kTestEDID, kTestEDID + arraysize(kTestEDID) - 1); + + // External Display + EXPECT_TRUE(CreateSnapshotFromEDID(true, edid, ¶ms)); + EXPECT_EQ("HP ZR30w", params.display_name); + EXPECT_EQ(1u, params.modes.size()); + EXPECT_TRUE(params.has_current_mode); + EXPECT_EQ("2560x1600", params.current_mode.size.ToString()); + EXPECT_EQ("641x400", params.physical_size.ToString()); + EXPECT_EQ(DISPLAY_CONNECTION_TYPE_INTERNAL, params.type); + + // Reset + params = DisplaySnapshot_Params(); + + // External Display + EXPECT_TRUE(CreateSnapshotFromEDID(false, edid, ¶ms)); + EXPECT_EQ("HP ZR30w", params.display_name); + EXPECT_EQ(1u, params.modes.size()); + EXPECT_TRUE(params.has_current_mode); + EXPECT_EQ("2560x1600", params.current_mode.size.ToString()); + EXPECT_EQ("641x400", params.physical_size.ToString()); + EXPECT_EQ(DISPLAY_CONNECTION_TYPE_VGA, params.type); +} + +TEST_F(DisplayUtilTest, EmptyEDID) { + DisplaySnapshot_Params params; + std::vector<uint8_t> edid; + + EXPECT_FALSE(CreateSnapshotFromEDID(true, std::vector<uint8_t>(), ¶ms)); +} + +} // namespace ui
diff --git a/ui/ozone/common/gpu/ozone_gpu_message_params.h b/ui/ozone/common/gpu/ozone_gpu_message_params.h index fe35df9..298a9fb 100644 --- a/ui/ozone/common/gpu/ozone_gpu_message_params.h +++ b/ui/ozone/common/gpu/ozone_gpu_message_params.h
@@ -11,10 +11,11 @@ #include "ui/display/types/display_constants.h" #include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/size.h" +#include "ui/ozone/ozone_export.h" namespace ui { -struct DisplayMode_Params { +struct OZONE_EXPORT DisplayMode_Params { DisplayMode_Params(); ~DisplayMode_Params(); @@ -23,7 +24,7 @@ float refresh_rate; }; -struct DisplaySnapshot_Params { +struct OZONE_EXPORT DisplaySnapshot_Params { DisplaySnapshot_Params(); ~DisplaySnapshot_Params();
diff --git a/ui/ozone/common/native_display_delegate_ozone.cc b/ui/ozone/common/native_display_delegate_ozone.cc index ac9fb16..7f7e15d 100644 --- a/ui/ozone/common/native_display_delegate_ozone.cc +++ b/ui/ozone/common/native_display_delegate_ozone.cc
@@ -17,9 +17,11 @@ } void NativeDisplayDelegateOzone::Initialize() { - DisplaySnapshot_Params params = CreateSnapshotFromCommandLine(); - if (params.type != DISPLAY_CONNECTION_TYPE_NONE) + DisplaySnapshot_Params params; + if (CreateSnapshotFromCommandLine(¶ms)) { + DCHECK_NE(DISPLAY_CONNECTION_TYPE_NONE, params.type); displays_.push_back(new DisplaySnapshotProxy(params)); + } } void NativeDisplayDelegateOzone::GrabServer() {
diff --git a/ui/ozone/ozone.gyp b/ui/ozone/ozone.gyp index d423056..ce55e3f 100644 --- a/ui/ozone/ozone.gyp +++ b/ui/ozone/ozone.gyp
@@ -56,6 +56,7 @@ '<(DEPTH)/ipc/ipc.gyp:ipc', '<(DEPTH)/skia/skia.gyp:skia', '<(DEPTH)/ui/display/display.gyp:display_types', + '<(DEPTH)/ui/display/display.gyp:display_util', '<(DEPTH)/ui/events/events.gyp:events', '<(DEPTH)/ui/events/ozone/events_ozone.gyp:events_ozone', '<(DEPTH)/ui/gfx/gfx.gyp:gfx', @@ -174,10 +175,11 @@ 'target_name': 'ozone_unittests', 'type': '<(gtest_target_type)', 'sources': [ + 'common/display_util_unittest.cc', 'run_all_unittests.cc', ], 'dependencies': [ - 'ozone_base', + 'ozone', '../../base/base.gyp:base', '../../base/base.gyp:test_support_base', '../../testing/gtest.gyp:gtest',
diff --git a/ui/ozone/platform/caca/caca_window_manager.cc b/ui/ozone/platform/caca/caca_window_manager.cc index c543a9b6..6f0b5ca 100644 --- a/ui/ozone/platform/caca/caca_window_manager.cc +++ b/ui/ozone/platform/caca/caca_window_manager.cc
@@ -100,7 +100,7 @@ } scoped_ptr<gfx::VSyncProvider> CacaSurface::CreateVSyncProvider() { - return scoped_ptr<gfx::VSyncProvider>(); + return nullptr; } } // namespace
diff --git a/ui/ozone/platform/dri/BUILD.gn b/ui/ozone/platform/dri/BUILD.gn index ebbf4d4..3a491677 100644 --- a/ui/ozone/platform/dri/BUILD.gn +++ b/ui/ozone/platform/dri/BUILD.gn
@@ -35,6 +35,8 @@ "dri_gpu_platform_support_.h", "dri_gpu_platform_support_host.cc", "dri_gpu_platform_support_host.h", + "dri_helper_thread.cc", + "dri_helper_thread.h", "dri_surface.cc", "dri_surface.h", "dri_surface_factory.cc", @@ -81,6 +83,7 @@ "//ipc", "//ui/base", "//ui/display/types", + "//ui/display/util", "//ui/events", "//ui/events/ozone:events_ozone_evdev", "//ui/events/ozone:events_ozone_layout",
diff --git a/ui/ozone/platform/dri/display_snapshot_dri.cc b/ui/ozone/platform/dri/display_snapshot_dri.cc index aa4ae30a..615ac47 100644 --- a/ui/ozone/platform/dri/display_snapshot_dri.cc +++ b/ui/ozone/platform/dri/display_snapshot_dri.cc
@@ -79,8 +79,8 @@ false, std::string(), std::vector<const DisplayMode*>(), - NULL, - NULL), + nullptr, + nullptr), connector_(connector->connector_id), crtc_(crtc->crtc_id), dpms_property_(drm->GetProperty(connector, "DPMS")) { @@ -98,7 +98,7 @@ if (!GetDisplayIdFromEDID(edid, index, &display_id_)) display_id_ = index; - ParseOutputDeviceData(edid, NULL, &display_name_); + ParseOutputDeviceData(edid, nullptr, &display_name_, nullptr, nullptr); ParseOutputOverscanFlag(edid, &overscan_flag_); } else { VLOG(1) << "Failed to get EDID blob for connector "
diff --git a/ui/ozone/platform/dri/dri.gypi b/ui/ozone/platform/dri/dri.gypi index 963959f9..0048f14c 100644 --- a/ui/ozone/platform/dri/dri.gypi +++ b/ui/ozone/platform/dri/dri.gypi
@@ -55,6 +55,8 @@ 'dri_gpu_platform_support.h', 'dri_gpu_platform_support_host.cc', 'dri_gpu_platform_support_host.h', + 'dri_helper_thread.cc', + 'dri_helper_thread.h', 'dri_surface.cc', 'dri_surface.h', 'dri_surface_factory.cc',
diff --git a/ui/ozone/platform/dri/dri_cursor.cc b/ui/ozone/platform/dri/dri_cursor.cc index f1571a4..7fb10a9 100644 --- a/ui/ozone/platform/dri/dri_cursor.cc +++ b/ui/ozone/platform/dri/dri_cursor.cc
@@ -192,6 +192,7 @@ #endif DCHECK(ui_task_runner_->BelongsToCurrentThread()); base::AutoLock lock(state_.lock); + state_.host_id = host_id; state_.send_runner = send_runner; state_.send_callback = send_callback; // Initial set for this GPU process will happen after the window @@ -201,8 +202,11 @@ void DriCursor::OnChannelDestroyed(int host_id) { DCHECK(ui_task_runner_->BelongsToCurrentThread()); base::AutoLock lock(state_.lock); - state_.send_runner = NULL; - state_.send_callback.Reset(); + if (state_.host_id == host_id) { + state_.host_id = -1; + state_.send_runner = NULL; + state_.send_callback.Reset(); + } } bool DriCursor::OnMessageReceived(const IPC::Message& message) { @@ -267,7 +271,8 @@ delete message; } -DriCursor::CursorState::CursorState() : window(gfx::kNullAcceleratedWidget) { +DriCursor::CursorState::CursorState() + : window(gfx::kNullAcceleratedWidget), host_id(-1) { } DriCursor::CursorState::~CursorState() {
diff --git a/ui/ozone/platform/dri/dri_cursor.h b/ui/ozone/platform/dri/dri_cursor.h index 755393a..f66f400 100644 --- a/ui/ozone/platform/dri/dri_cursor.h +++ b/ui/ozone/platform/dri/dri_cursor.h
@@ -104,6 +104,8 @@ // The bounds of the display under the cursor. gfx::Rect bounds; + int host_id; + // Callback for IPC updates. base::Callback<void(IPC::Message*)> send_callback; scoped_refptr<base::SingleThreadTaskRunner> send_runner;
diff --git a/ui/ozone/platform/dri/dri_gpu_platform_support.cc b/ui/ozone/platform/dri/dri_gpu_platform_support.cc index 994589c..fccb544 100644 --- a/ui/ozone/platform/dri/dri_gpu_platform_support.cc +++ b/ui/ozone/platform/dri/dri_gpu_platform_support.cc
@@ -5,6 +5,7 @@ #include "ui/ozone/platform/dri/dri_gpu_platform_support.h" #include "base/bind.h" +#include "base/command_line.h" #include "base/thread_task_runner_handle.h" #include "ipc/ipc_message_macros.h" #include "ui/display/types/display_mode.h" @@ -12,9 +13,12 @@ #include "ui/ozone/common/display_util.h" #include "ui/ozone/common/gpu/ozone_gpu_message_params.h" #include "ui/ozone/common/gpu/ozone_gpu_messages.h" +#include "ui/ozone/platform/dri/dri_helper_thread.h" #include "ui/ozone/platform/dri/dri_window_delegate_impl.h" #include "ui/ozone/platform/dri/dri_window_delegate_manager.h" +#include "ui/ozone/platform/dri/dri_wrapper.h" #include "ui/ozone/platform/dri/native_display_delegate_dri.h" +#include "ui/ozone/public/ozone_switches.h" namespace ui { @@ -28,9 +32,12 @@ class DriGpuPlatformSupportMessageFilter : public IPC::MessageFilter { public: - DriGpuPlatformSupportMessageFilter(DriWindowDelegateManager* window_manager, - IPC::Listener* main_thread_listener) + DriGpuPlatformSupportMessageFilter( + DriWindowDelegateManager* window_manager, + const base::Closure& on_filter_added_callback, + IPC::Listener* main_thread_listener) : window_manager_(window_manager), + on_filter_added_callback_(on_filter_added_callback), main_thread_listener_(main_thread_listener), main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()), pending_main_thread_operations_(0), @@ -38,6 +45,7 @@ void OnFilterAdded(IPC::Sender* sender) override { io_thread_task_runner_ = base::ThreadTaskRunnerHandle::Get(); + main_thread_task_runner_->PostTask(FROM_HERE, on_filter_added_callback_); } // This code is meant to be very temporary and only as a special case to fix @@ -146,6 +154,7 @@ } DriWindowDelegateManager* window_manager_; + base::Closure on_filter_added_callback_; IPC::Listener* main_thread_listener_; scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_; scoped_refptr<base::SingleThreadTaskRunner> io_thread_task_runner_; @@ -164,7 +173,10 @@ window_manager_(window_manager), screen_manager_(screen_manager), ndd_(ndd.Pass()) { - filter_ = new DriGpuPlatformSupportMessageFilter(window_manager, this); + filter_ = new DriGpuPlatformSupportMessageFilter( + window_manager, + base::Bind(&DriGpuPlatformSupport::OnFilterAdded, base::Unretained(this)), + this); } DriGpuPlatformSupport::~DriGpuPlatformSupport() { @@ -346,6 +358,17 @@ callback.Run(); } +void DriGpuPlatformSupport::OnFilterAdded() { + base::CommandLine* cmd = base::CommandLine::ForCurrentProcess(); + // Only surfaceless path supports async page flips. So we only initialize the + // helper thread if we're using async page flips. + if (!helper_thread_.IsRunning() && + cmd->HasSwitch(switches::kOzoneUseSurfaceless)) { + helper_thread_.Initialize(); + drm_->InitializeTaskRunner(helper_thread_.task_runner()); + } +} + IPC::MessageFilter* DriGpuPlatformSupport::GetMessageFilter() { return filter_.get(); }
diff --git a/ui/ozone/platform/dri/dri_gpu_platform_support.h b/ui/ozone/platform/dri/dri_gpu_platform_support.h index 71925ae..daae2ec 100644 --- a/ui/ozone/platform/dri/dri_gpu_platform_support.h +++ b/ui/ozone/platform/dri/dri_gpu_platform_support.h
@@ -10,6 +10,7 @@ #include "base/memory/scoped_vector.h" #include "ipc/message_filter.h" #include "ui/gfx/native_widget_types.h" +#include "ui/ozone/platform/dri/dri_helper_thread.h" #include "ui/ozone/public/gpu_platform_support.h" class SkBitmap; @@ -76,11 +77,14 @@ void OnAddGraphicsDevice(const base::FilePath& path); void OnRemoveGraphicsDevice(const base::FilePath& path); + void OnFilterAdded(); + IPC::Sender* sender_; // Not owned. DriWrapper* drm_; // Not owned. DriWindowDelegateManager* window_manager_; // Not owned. ScreenManager* screen_manager_; // Not owned. + DriHelperThread helper_thread_; scoped_ptr<NativeDisplayDelegateDri> ndd_; ScopedVector<GpuPlatformSupport> handlers_; scoped_refptr<IPC::MessageFilter> filter_;
diff --git a/ui/ozone/platform/dri/dri_helper_thread.cc b/ui/ozone/platform/dri/dri_helper_thread.cc new file mode 100644 index 0000000..4ca33017 --- /dev/null +++ b/ui/ozone/platform/dri/dri_helper_thread.cc
@@ -0,0 +1,23 @@ +// Copyright 2015 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 "ui/ozone/platform/dri/dri_helper_thread.h" + +namespace ui { + +DriHelperThread::DriHelperThread() : Thread("DriHelperThread") { +} + +DriHelperThread::~DriHelperThread() { + Stop(); +} + +void DriHelperThread::Initialize() { + DCHECK(!IsRunning()); + + if (!StartWithOptions(base::Thread::Options(base::MessageLoop::TYPE_IO, 0))) + LOG(FATAL) << "Failed to start the IO helper thread"; +} + +} // namespace ui
diff --git a/ui/ozone/platform/dri/dri_helper_thread.h b/ui/ozone/platform/dri/dri_helper_thread.h new file mode 100644 index 0000000..fea01d9 --- /dev/null +++ b/ui/ozone/platform/dri/dri_helper_thread.h
@@ -0,0 +1,27 @@ +// Copyright 2015 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 UI_OZONE_PLATFORM_DRI_DRI_HELPER_THREAD_H_ +#define UI_OZONE_PLATFORM_DRI_DRI_HELPER_THREAD_H_ + +#include "base/threading/thread.h" + +namespace ui { + +class DriHelperThread : public base::Thread { + public: + DriHelperThread(); + ~DriHelperThread() override; + + // Call to start the thread. This needs to be called after the GPU entered the + // sandbox. + void Initialize(); + + private: + DISALLOW_COPY_AND_ASSIGN(DriHelperThread); +}; + +} // namespace ui + +#endif // UI_OZONE_PLATFORM_DRI_DRI_HELPER_THREAD_H_
diff --git a/ui/ozone/platform/dri/dri_wrapper.cc b/ui/ozone/platform/dri/dri_wrapper.cc index 929dd27..257eae2 100644 --- a/ui/ozone/platform/dri/dri_wrapper.cc +++ b/ui/ozone/platform/dri/dri_wrapper.cc
@@ -144,11 +144,8 @@ DISALLOW_COPY_AND_ASSIGN(IOWatcher); }; -DriWrapper::DriWrapper(const char* device_path, bool use_sync_flips) - : fd_(-1), - use_sync_flips_(use_sync_flips), - device_path_(device_path), - io_thread_("DriIOThread") { +DriWrapper::DriWrapper(const char* device_path) + : fd_(-1), device_path_(device_path) { plane_manager_.reset(new HardwareDisplayPlaneManagerLegacy()); } @@ -168,14 +165,11 @@ LOG(ERROR) << "Failed to initialize the plane manager"; } -void DriWrapper::InitializeIOWatcher() { - if (!use_sync_flips_ && !watcher_) { - if (!io_thread_.StartWithOptions( - base::Thread::Options(base::MessageLoop::TYPE_IO, 0))) - LOG(FATAL) << "Failed to start the IO helper thread"; - - watcher_ = new IOWatcher(fd_, io_thread_.task_runner()); - } +void DriWrapper::InitializeTaskRunner( + const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) { + DCHECK(!task_runner_); + task_runner_ = task_runner; + watcher_ = new IOWatcher(fd_, task_runner_); } ScopedDrmCrtcPtr DriWrapper::GetCrtc(uint32_t crtc_id) { @@ -278,7 +272,10 @@ payload.get())) { // If successful the payload will be removed by a PageFlip event. ignore_result(payload.release()); - if (use_sync_flips_) { + + // If a task runner isn't installed then fall back to synchronously handling + // the page flip events. + if (!task_runner_) { TRACE_EVENT1("dri", "OnDrmEvent", "socket", fd_); drmEventContext event; @@ -287,8 +284,6 @@ event.vblank_handler = nullptr; drmHandleEvent(fd_, &event); - } else { - InitializeIOWatcher(); } return true;
diff --git a/ui/ozone/platform/dri/dri_wrapper.h b/ui/ozone/platform/dri/dri_wrapper.h index 0dfa8669..381459e 100644 --- a/ui/ozone/platform/dri/dri_wrapper.h +++ b/ui/ozone/platform/dri/dri_wrapper.h
@@ -12,7 +12,6 @@ #include "base/callback.h" #include "base/macros.h" #include "base/memory/scoped_vector.h" -#include "base/threading/thread.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/rect_f.h" #include "ui/gfx/overlay_transform.h" @@ -24,6 +23,10 @@ struct SkImageInfo; +namespace base { +class SingleThreadTaskRunner; +} // namespace base + namespace ui { class HardwareDisplayPlaneManager; @@ -37,12 +40,16 @@ unsigned int /* seconds */, unsigned int /* useconds */)> PageFlipCallback; - DriWrapper(const char* device_path, bool use_sync_flips); + DriWrapper(const char* device_path); virtual ~DriWrapper(); // Open device. virtual void Initialize(); + // |task_runner| will be used to asynchronously page flip. + virtual void InitializeTaskRunner( + const scoped_refptr<base::SingleThreadTaskRunner>& task_runner); + // Get the CRTC state. This is generally used to save state before using the // CRTC. When the user finishes using the CRTC, the user should restore the // CRTC to it's initial state. Use |SetCrtc| to restore the state. @@ -152,10 +159,6 @@ HardwareDisplayPlaneManager* plane_manager() { return plane_manager_.get(); } protected: - // Responsible for late initialization of the IO thread. This needs to happen - // after the sandbox is up, thus the late initialization. - virtual void InitializeIOWatcher(); - // The file descriptor associated with this wrapper. All DRM operations will // be performed using this FD. // TODO(dnicoara) Make this a base::File @@ -163,9 +166,6 @@ scoped_ptr<HardwareDisplayPlaneManager> plane_manager_; - // If we need to block when performing page flips this is set to true. - bool use_sync_flips_; - private: class IOWatcher; @@ -173,9 +173,7 @@ const char* device_path_; // Helper thread to perform IO listener operations. - // TODO(dnicoara) This should really be supported by the main thread. - // Alternatively we should have a way to access the IO thread's task runner. - base::Thread io_thread_; + scoped_refptr<base::SingleThreadTaskRunner> task_runner_; // Watcher for |fd_| listening for page flip events. scoped_refptr<IOWatcher> watcher_;
diff --git a/ui/ozone/platform/dri/gbm_surface_factory.cc b/ui/ozone/platform/dri/gbm_surface_factory.cc index 293d8ae..c5da63d 100644 --- a/ui/ozone/platform/dri/gbm_surface_factory.cc +++ b/ui/ozone/platform/dri/gbm_surface_factory.cc
@@ -134,7 +134,7 @@ GbmSurfaceFactory::CreateSurfacelessEGLSurfaceForWidget( gfx::AcceleratedWidget widget) { if (!allow_surfaceless_) - return scoped_ptr<SurfaceOzoneEGL>(); + return nullptr; DriWindowDelegate* delegate = GetOrCreateWindowDelegate(widget); return scoped_ptr<SurfaceOzoneEGL>(new GbmSurfaceless(delegate));
diff --git a/ui/ozone/platform/dri/gbm_wrapper.cc b/ui/ozone/platform/dri/gbm_wrapper.cc index 73de7d9..4b1298f 100644 --- a/ui/ozone/platform/dri/gbm_wrapper.cc +++ b/ui/ozone/platform/dri/gbm_wrapper.cc
@@ -8,8 +8,8 @@ namespace ui { -GbmWrapper::GbmWrapper(const char* device_path, bool use_sync_flips) - : DriWrapper(device_path, use_sync_flips), device_(nullptr) { +GbmWrapper::GbmWrapper(const char* device_path) + : DriWrapper(device_path), device_(nullptr) { } GbmWrapper::~GbmWrapper() {
diff --git a/ui/ozone/platform/dri/gbm_wrapper.h b/ui/ozone/platform/dri/gbm_wrapper.h index a89a87e..d7a4056 100644 --- a/ui/ozone/platform/dri/gbm_wrapper.h +++ b/ui/ozone/platform/dri/gbm_wrapper.h
@@ -13,7 +13,7 @@ class GbmWrapper : public DriWrapper { public: - GbmWrapper(const char* device_path, bool use_sync_flips); + GbmWrapper(const char* device_path); ~GbmWrapper() override; gbm_device* device() const { return device_; }
diff --git a/ui/ozone/platform/dri/hardware_display_controller.cc b/ui/ozone/platform/dri/hardware_display_controller.cc index 375cc82b..6d3c33c 100644 --- a/ui/ozone/platform/dri/hardware_display_controller.cc +++ b/ui/ozone/platform/dri/hardware_display_controller.cc
@@ -185,7 +185,7 @@ } } - return scoped_ptr<CrtcController>(); + return nullptr; } bool HardwareDisplayController::HasCrtc(uint32_t crtc) const {
diff --git a/ui/ozone/platform/dri/native_display_delegate_proxy.cc b/ui/ozone/platform/dri/native_display_delegate_proxy.cc index 29dc5380..8ad2c40 100644 --- a/ui/ozone/platform/dri/native_display_delegate_proxy.cc +++ b/ui/ozone/platform/dri/native_display_delegate_proxy.cc
@@ -7,6 +7,7 @@ #include <stdio.h> #include "base/logging.h" +#include "base/threading/thread_restrictions.h" #include "ui/display/types/display_snapshot.h" #include "ui/display/types/native_display_observer.h" #include "ui/events/ozone/device/device_event.h" @@ -63,9 +64,22 @@ if (!displays_.empty()) return; + DisplaySnapshot_Params params; + bool success = false; + { + // The file generated by frecon that contains EDID for the 1st display. + const base::FilePath kEDIDFile("/tmp/display_info.bin"); - DisplaySnapshot_Params params = CreateSnapshotFromCommandLine(); - if (params.type != DISPLAY_CONNECTION_TYPE_NONE) { + // Just read it on current thread as this is necessary information + // to start. This access only tmpfs, which is fast. + // TODO(dnicoara|oshima): crbug.com/450886. + base::ThreadRestrictions::ScopedAllowIO allow_io; + success = CreateSnapshotFromEDIDFile(kEDIDFile, ¶ms); + } + + // Fallback to command line if the file doesn't exit or failed to read. + if (success || CreateSnapshotFromCommandLine(¶ms)) { + DCHECK_NE(DISPLAY_CONNECTION_TYPE_NONE, params.type); displays_.push_back(new DriDisplaySnapshotProxy(params, display_manager_)); has_dummy_display_ = true; }
diff --git a/ui/ozone/platform/dri/ozone_platform_dri.cc b/ui/ozone/platform/dri/ozone_platform_dri.cc index a91ea1f..066ede2 100644 --- a/ui/ozone/platform/dri/ozone_platform_dri.cc +++ b/ui/ozone/platform/dri/ozone_platform_dri.cc
@@ -47,7 +47,7 @@ class OzonePlatformDri : public OzonePlatform { public: OzonePlatformDri() - : dri_(new DriWrapper(kDefaultGraphicsCardPath, true)), + : dri_(new DriWrapper(kDefaultGraphicsCardPath)), buffer_generator_(new DriBufferGenerator()), screen_manager_(new ScreenManager(dri_.get(), buffer_generator_.get())), device_manager_(CreateDeviceManager()) {}
diff --git a/ui/ozone/platform/dri/ozone_platform_gbm.cc b/ui/ozone/platform/dri/ozone_platform_gbm.cc index 2b401255..958b5a47 100644 --- a/ui/ozone/platform/dri/ozone_platform_gbm.cc +++ b/ui/ozone/platform/dri/ozone_platform_gbm.cc
@@ -152,7 +152,7 @@ void InitializeGPU() override { gl_api_loader_.reset(new GlApiLoader()); // Async page flips are supported only on surfaceless mode. - gbm_.reset(new GbmWrapper(kDefaultGraphicsCardPath, !use_surfaceless_)); + gbm_.reset(new GbmWrapper(kDefaultGraphicsCardPath)); gbm_->Initialize(); buffer_generator_.reset(new GbmBufferGenerator()); screen_manager_.reset(
diff --git a/ui/ozone/platform/dri/test/mock_dri_wrapper.cc b/ui/ozone/platform/dri/test/mock_dri_wrapper.cc index 3f65ffa..5c0f1bf 100644 --- a/ui/ozone/platform/dri/test/mock_dri_wrapper.cc +++ b/ui/ozone/platform/dri/test/mock_dri_wrapper.cc
@@ -40,7 +40,7 @@ } // namespace MockDriWrapper::MockDriWrapper(int fd) - : DriWrapper("", true), + : DriWrapper(""), get_crtc_call_count_(0), set_crtc_call_count_(0), restore_crtc_call_count_(0), @@ -61,7 +61,7 @@ bool use_sync_flips, std::vector<uint32_t> crtcs, size_t planes_per_crtc) - : DriWrapper("", use_sync_flips), + : DriWrapper(""), get_crtc_call_count_(0), set_crtc_call_count_(0), restore_crtc_call_count_(0), @@ -73,6 +73,7 @@ add_framebuffer_expectation_(true), page_flip_expectation_(true), create_dumb_buffer_expectation_(true), + use_sync_flips_(use_sync_flips), current_framebuffer_(0) { fd_ = fd; plane_manager_.reset(
diff --git a/ui/ozone/platform/dri/test/mock_dri_wrapper.h b/ui/ozone/platform/dri/test/mock_dri_wrapper.h index 9f64b75d..adc89fbb 100644 --- a/ui/ozone/platform/dri/test/mock_dri_wrapper.h +++ b/ui/ozone/platform/dri/test/mock_dri_wrapper.h
@@ -116,6 +116,8 @@ bool page_flip_expectation_; bool create_dumb_buffer_expectation_; + bool use_sync_flips_; + uint32_t current_framebuffer_; std::vector<skia::RefPtr<SkSurface> > buffers_;
diff --git a/ui/ozone/platform/egltest/ozone_platform_egltest.cc b/ui/ozone/platform/egltest/ozone_platform_egltest.cc index 032f81c..0e432981 100644 --- a/ui/ozone/platform/egltest/ozone_platform_egltest.cc +++ b/ui/ozone/platform/egltest/ozone_platform_egltest.cc
@@ -219,7 +219,7 @@ } scoped_ptr<gfx::VSyncProvider> CreateVSyncProvider() override { - return scoped_ptr<gfx::VSyncProvider>(); + return nullptr; } private:
diff --git a/ui/ozone/platform/test/test_window_manager.cc b/ui/ozone/platform/test/test_window_manager.cc index dd557f3..3ff3a47 100644 --- a/ui/ozone/platform/test/test_window_manager.cc +++ b/ui/ozone/platform/test/test_window_manager.cc
@@ -54,7 +54,7 @@ } } scoped_ptr<gfx::VSyncProvider> CreateVSyncProvider() override { - return scoped_ptr<gfx::VSyncProvider>(); + return nullptr; } private:
diff --git a/ui/ozone/public/surface_factory_ozone.cc b/ui/ozone/public/surface_factory_ozone.cc index 3d0f5ca..1c57038d 100644 --- a/ui/ozone/public/surface_factory_ozone.cc +++ b/ui/ozone/public/surface_factory_ozone.cc
@@ -42,20 +42,20 @@ scoped_ptr<SurfaceOzoneEGL> SurfaceFactoryOzone::CreateEGLSurfaceForWidget( gfx::AcceleratedWidget widget) { NOTIMPLEMENTED(); - return scoped_ptr<SurfaceOzoneEGL>(); + return nullptr; } scoped_ptr<SurfaceOzoneEGL> SurfaceFactoryOzone::CreateSurfacelessEGLSurfaceForWidget( gfx::AcceleratedWidget widget) { NOTIMPLEMENTED(); - return scoped_ptr<SurfaceOzoneEGL>(); + return nullptr; } scoped_ptr<SurfaceOzoneCanvas> SurfaceFactoryOzone::CreateCanvasForWidget( gfx::AcceleratedWidget widget) { NOTIMPLEMENTED(); - return scoped_ptr<SurfaceOzoneCanvas>(); + return nullptr; } const int32* SurfaceFactoryOzone::GetEGLSurfaceProperties(
diff --git a/ui/ozone/public/ui_thread_gpu.cc b/ui/ozone/public/ui_thread_gpu.cc index ccc9849..e64e13c 100644 --- a/ui/ozone/public/ui_thread_gpu.cc +++ b/ui/ozone/public/ui_thread_gpu.cc
@@ -8,6 +8,7 @@ #include "ipc/ipc_listener.h" #include "ipc/ipc_message.h" #include "ipc/ipc_sender.h" +#include "ipc/message_filter.h" #include "ui/ozone/public/gpu_platform_support.h" #include "ui/ozone/public/gpu_platform_support_host.h" #include "ui/ozone/public/ozone_platform.h" @@ -29,6 +30,11 @@ task_runner_ = base::ThreadTaskRunnerHandle::Get(); ui::OzonePlatform::GetInstance() ->GetGpuPlatformSupport() + ->GetMessageFilter() + ->OnFilterAdded(this); + + ui::OzonePlatform::GetInstance() + ->GetGpuPlatformSupport() ->OnChannelEstablished(this); }
diff --git a/ui/strings/app_locale_settings.grd b/ui/strings/app_locale_settings.grd index 2ab29ad..19bb7e5 100644 --- a/ui/strings/app_locale_settings.grd +++ b/ui/strings/app_locale_settings.grd
@@ -256,7 +256,7 @@ <if expr="chromeos"> <!-- The font name like: 'Font Name, 10' --> <message name="IDS_UI_FONT_FAMILY_CROS" use_name_for_id="true"> - Noto Sans UI,ui-sans, 12px + Noto Sans UI, 12px </message> <!-- The font used in Web UI (e.g. History). -->
diff --git a/ui/strings/translations/app_locale_settings_ar.xtb b/ui/strings/translations/app_locale_settings_ar.xtb index 925971ee..a6193617 100644 --- a/ui/strings/translations/app_locale_settings_ar.xtb +++ b/ui/strings/translations/app_locale_settings_ar.xtb
@@ -3,7 +3,7 @@ <translationbundle lang="ar"> <translation id="IDS_MINIMUM_UI_FONT_SIZE">10</translation> <if expr="chromeos"> - <translation id="IDS_UI_FONT_FAMILY_CROS">Noto Sans UI, Noto Naskh Arabic UI, ui-sans, 13px</translation> + <translation id="IDS_UI_FONT_FAMILY_CROS">Noto Sans UI, Noto Naskh Arabic UI, 13px</translation> <translation id="IDS_WEB_FONT_FAMILY">Noto Sans UI, Noto Naskh Arabic UI, sans-serif</translation> </if> </translationbundle>
diff --git a/ui/strings/translations/app_locale_settings_bn.xtb b/ui/strings/translations/app_locale_settings_bn.xtb index 3777caa..b5ad62e 100644 --- a/ui/strings/translations/app_locale_settings_bn.xtb +++ b/ui/strings/translations/app_locale_settings_bn.xtb
@@ -14,7 +14,7 @@ <translation id="IDS_WEB_FONT_FAMILY">Lohit Bengali</translation> </if> <if expr="chromeos"> - <translation id="IDS_UI_FONT_FAMILY_CROS">Noto Sans UI, Noto Sans Bengali UI, ui-sans, 13px</translation> + <translation id="IDS_UI_FONT_FAMILY_CROS">Noto Sans UI, Noto Sans Bengali UI, 13px</translation> <translation id="IDS_WEB_FONT_FAMILY">Noto Sans UI, Noto Sans Bengali UI, sans-serif</translation> </if> </translationbundle>
diff --git a/ui/strings/translations/app_locale_settings_hi.xtb b/ui/strings/translations/app_locale_settings_hi.xtb index 64abc26..3e482aa 100644 --- a/ui/strings/translations/app_locale_settings_hi.xtb +++ b/ui/strings/translations/app_locale_settings_hi.xtb
@@ -5,7 +5,7 @@ <translation id="IDS_UI_FONT_SIZE_SCALER">125</translation> <translation id="IDS_MINIMUM_UI_FONT_SIZE">10</translation> <if expr="chromeos"> - <translation id="IDS_UI_FONT_FAMILY_CROS">Noto Sans UI,Noto Sans Devanagari UI,ui-sans, 13px</translation> + <translation id="IDS_UI_FONT_FAMILY_CROS">Noto Sans UI,Noto Sans Devanagari UI, 13px</translation> <translation id="IDS_WEB_FONT_FAMILY">Noto Sans UI,Noto Sans Devanagari UI,sans-serif</translation> </if> </translationbundle>
diff --git a/ui/strings/translations/app_locale_settings_ja.xtb b/ui/strings/translations/app_locale_settings_ja.xtb index 8a36c05..bcfc6b9d 100644 --- a/ui/strings/translations/app_locale_settings_ja.xtb +++ b/ui/strings/translations/app_locale_settings_ja.xtb
@@ -2,7 +2,7 @@ <!DOCTYPE translationbundle> <translationbundle lang="ja"> <translation id="IDS_MINIMUM_UI_FONT_SIZE">10</translation> -<translation id="IDS_UI_FONT_FAMILY_CROS">Noto Sans UI,Noto Sans CJK JP,ui-sans, 13px</translation> +<translation id="IDS_UI_FONT_FAMILY_CROS">Noto Sans UI,Noto Sans CJK JP, 13px</translation> <if expr="is_win"> <translation id="IDS_WEB_FONT_FAMILY">'Segoe UI',Arial,Meiryo,sans-serif</translation> <translation id="IDS_WEB_FONT_FAMILY_XP">Arial,Meiryo,'MS PGothic',sans-serif</translation>
diff --git a/ui/strings/translations/app_locale_settings_kn.xtb b/ui/strings/translations/app_locale_settings_kn.xtb index a5d7bb9..c90fe9d 100644 --- a/ui/strings/translations/app_locale_settings_kn.xtb +++ b/ui/strings/translations/app_locale_settings_kn.xtb
@@ -7,7 +7,7 @@ <translation id="IDS_UI_FONT_SIZE_SCALER">130</translation> </if> <if expr="chromeos"> - <translation id="IDS_UI_FONT_FAMILY_CROS">Noto Sans UI, Noto Sans Kannada UI,ui-sans, 13px</translation> + <translation id="IDS_UI_FONT_FAMILY_CROS">Noto Sans UI, Noto Sans Kannada UI, 13px</translation> <translation id="IDS_WEB_FONT_FAMILY">Noto Sans UI, Noto Sans Kannada UI, sans-serif</translation> </if> </translationbundle>
diff --git a/ui/strings/translations/app_locale_settings_ko.xtb b/ui/strings/translations/app_locale_settings_ko.xtb index c215e669..904469b 100644 --- a/ui/strings/translations/app_locale_settings_ko.xtb +++ b/ui/strings/translations/app_locale_settings_ko.xtb
@@ -2,7 +2,7 @@ <!DOCTYPE translationbundle> <translationbundle lang="ko"> <translation id="IDS_MINIMUM_UI_FONT_SIZE">10</translation> -<translation id="IDS_UI_FONT_FAMILY_CROS">Noto Sans UI,Noto Sans CJK KR,ui-sans, 13px</translation> +<translation id="IDS_UI_FONT_FAMILY_CROS">Noto Sans UI,Noto Sans CJK KR, 13px</translation> <if expr="is_win"> <translation id="IDS_WEB_FONT_FAMILY">'Segoe UI',Arial,'Malgun Gothic',Gulim,sans-serif</translation> <translation id="IDS_WEB_FONT_FAMILY_XP">Arial,'Malgun Gothic',Gulim,sans-serif</translation>
diff --git a/ui/strings/translations/app_locale_settings_ml.xtb b/ui/strings/translations/app_locale_settings_ml.xtb index 9df3a5a..5d5fdcc 100644 --- a/ui/strings/translations/app_locale_settings_ml.xtb +++ b/ui/strings/translations/app_locale_settings_ml.xtb
@@ -13,7 +13,7 @@ <translation id="IDS_WEB_FONT_FAMILY">Arial,AnjaliOldLipi,Rachana,Kartika,sans-serif</translation> </if> <if expr="chromeos"> - <translation id="IDS_UI_FONT_FAMILY_CROS">Noto Sans UI, Noto Sans Malayalam UI,ui-sans, 13px</translation> + <translation id="IDS_UI_FONT_FAMILY_CROS">Noto Sans UI, Noto Sans Malayalam UI, 13px</translation> <translation id="IDS_WEB_FONT_FAMILY">Noto Sans UI, Noto Sans Malayalam UI, sans-serif</translation> </if> </translationbundle>
diff --git a/ui/strings/translations/app_locale_settings_mr.xtb b/ui/strings/translations/app_locale_settings_mr.xtb index 1e0754fc..df85034 100644 --- a/ui/strings/translations/app_locale_settings_mr.xtb +++ b/ui/strings/translations/app_locale_settings_mr.xtb
@@ -4,7 +4,7 @@ <translation id="IDS_UI_FONT_SIZE_SCALER_XP">140</translation> <translation id="IDS_UI_FONT_SIZE_SCALER">125</translation> <translation id="IDS_MINIMUM_UI_FONT_SIZE">10</translation> -<translation id="IDS_UI_FONT_FAMILY_CROS">Noto Sans UI,Noto Sans Devanagari UI,ui-sans, 13px</translation> +<translation id="IDS_UI_FONT_FAMILY_CROS">Noto Sans UI,Noto Sans Devanagari UI, 13px</translation> <if expr="chromeos"> <translation id="IDS_WEB_FONT_FAMILY">Noto Sans UI,Noto Sans Devanagari UI,sans-serif</translation> </if>
diff --git a/ui/strings/translations/app_locale_settings_ta.xtb b/ui/strings/translations/app_locale_settings_ta.xtb index 9051adc..37b866c 100644 --- a/ui/strings/translations/app_locale_settings_ta.xtb +++ b/ui/strings/translations/app_locale_settings_ta.xtb
@@ -1,7 +1,7 @@ <?xml version="1.0" ?> <!DOCTYPE translationbundle> <translationbundle lang="ta"> -<translation id="IDS_UI_FONT_FAMILY_CROS">Noto Sans UI,Noto Sans Tamil UI,ui-sans, 13px</translation> +<translation id="IDS_UI_FONT_FAMILY_CROS">Noto Sans UI,Noto Sans Tamil UI, 13px</translation> <if expr="chromeos"> <translation id="IDS_WEB_FONT_FAMILY">Noto Sans UI,Noto Sans Tamil UI,sans-serif</translation> </if>
diff --git a/ui/strings/translations/app_locale_settings_te.xtb b/ui/strings/translations/app_locale_settings_te.xtb index 8346fb0..e612c59 100644 --- a/ui/strings/translations/app_locale_settings_te.xtb +++ b/ui/strings/translations/app_locale_settings_te.xtb
@@ -7,7 +7,7 @@ <translation id="IDS_UI_FONT_SIZE_SCALER">130</translation> </if> <if expr="chromeos"> - <translation id="IDS_UI_FONT_FAMILY_CROS">Noto Sans UI, Noto Sans Telugu UI,ui-sans, 13px</translation> + <translation id="IDS_UI_FONT_FAMILY_CROS">Noto Sans UI, Noto Sans Telugu UI, 13px</translation> <translation id="IDS_WEB_FONT_FAMILY">Noto Sans UI, Noto Sans Telugu UI, sans-serif</translation> </if> </translationbundle>
diff --git a/ui/strings/translations/app_locale_settings_th.xtb b/ui/strings/translations/app_locale_settings_th.xtb index 9c6b6f5..f5ccc927 100644 --- a/ui/strings/translations/app_locale_settings_th.xtb +++ b/ui/strings/translations/app_locale_settings_th.xtb
@@ -2,7 +2,7 @@ <!DOCTYPE translationbundle> <translationbundle lang="th"> <translation id="IDS_MINIMUM_UI_FONT_SIZE">10</translation> -<translation id="IDS_UI_FONT_FAMILY_CROS">Noto Sans UI,Noto Sans Thai UI,ui-sans, 13px</translation> +<translation id="IDS_UI_FONT_FAMILY_CROS">Noto Sans UI,Noto Sans Thai UI, 13px</translation> <if expr="is_win"> <translation id="IDS_WEB_FONT_FAMILY">Tahoma,sans-serif</translation> <translation id="IDS_WEB_FONT_FAMILY_XP">Tahoma,sans-serif</translation>
diff --git a/ui/strings/translations/app_locale_settings_zh-CN.xtb b/ui/strings/translations/app_locale_settings_zh-CN.xtb index adedfed..a082efa 100644 --- a/ui/strings/translations/app_locale_settings_zh-CN.xtb +++ b/ui/strings/translations/app_locale_settings_zh-CN.xtb
@@ -2,7 +2,7 @@ <!DOCTYPE translationbundle> <translationbundle lang="zh-CN"> <translation id="IDS_MINIMUM_UI_FONT_SIZE">10</translation> -<translation id="IDS_UI_FONT_FAMILY_CROS">Noto Sans UI,Noto Sans CJK SC,ui-sans, 13px</translation> +<translation id="IDS_UI_FONT_FAMILY_CROS">Noto Sans UI,Noto Sans CJK SC, 13px</translation> <if expr="is_win"> <translation id="IDS_WEB_FONT_FAMILY">'Segoe UI',Arial,'Microsoft Yahei',sans-serif</translation> <translation id="IDS_WEB_FONT_FAMILY_XP">Arial,'Microsoft Yahei',Simsun,sans-serif</translation>
diff --git a/ui/strings/translations/app_locale_settings_zh-TW.xtb b/ui/strings/translations/app_locale_settings_zh-TW.xtb index ae5d40c0..41a6b6d 100644 --- a/ui/strings/translations/app_locale_settings_zh-TW.xtb +++ b/ui/strings/translations/app_locale_settings_zh-TW.xtb
@@ -2,7 +2,7 @@ <!DOCTYPE translationbundle> <translationbundle lang="zh-TW"> <translation id="IDS_MINIMUM_UI_FONT_SIZE">10</translation> -<translation id="IDS_UI_FONT_FAMILY_CROS">Noto Sans UI,Noto Sans CJK TC,ui-sans, 13px</translation> +<translation id="IDS_UI_FONT_FAMILY_CROS">Noto Sans UI,Noto Sans CJK TC, 13px</translation> <if expr="is_win"> <translation id="IDS_WEB_FONT_FAMILY">'Segoe UI',Arial,'Microsoft Jhenghei',sans-serif</translation> <translation id="IDS_WEB_FONT_FAMILY_XP">Arial,'Microsoft Jhenghei',PMingLiu,sans-serif</translation>
diff --git a/ui/touch_selection/touch_selection_controller.cc b/ui/touch_selection/touch_selection_controller.cc index f5a4bda..d53f4095 100644 --- a/ui/touch_selection/touch_selection_controller.cc +++ b/ui/touch_selection/touch_selection_controller.cc
@@ -10,6 +10,18 @@ namespace ui { namespace { +gfx::Vector2dF ComputeLineOffsetFromBottom(const SelectionBound& bound) { + gfx::Vector2dF line_offset = + gfx::ScaleVector2d(bound.edge_top() - bound.edge_bottom(), 0.5f); + // An offset of 5 DIPs is sufficient for most line sizes. For small lines, + // using half the line height avoids synthesizing a point on a line above + // (or below) the intended line. + const gfx::Vector2dF kMaxLineOffset(5.f, 5.f); + line_offset.SetToMin(kMaxLineOffset); + line_offset.SetToMax(-kMaxLineOffset); + return line_offset; +} + TouchHandleOrientation ToTouchHandleOrientation(SelectionBound::Type type) { switch (type) { case SelectionBound::LEFT: @@ -239,7 +251,7 @@ const gfx::PointF& position) { // As the position corresponds to the bottom left point of the selection // bound, offset it by half the corresponding line height. - gfx::Vector2dF line_offset = &handle == end_selection_handle_.get() + gfx::Vector2dF line_offset = &handle == start_selection_handle_.get() ? GetStartLineOffset() : GetEndLineOffset(); gfx::PointF line_position = position + line_offset; @@ -408,11 +420,11 @@ } gfx::Vector2dF TouchSelectionController::GetStartLineOffset() const { - return gfx::ScaleVector2d(start_.edge_top() - start_.edge_bottom(), 0.5f); + return ComputeLineOffsetFromBottom(start_); } gfx::Vector2dF TouchSelectionController::GetEndLineOffset() const { - return gfx::ScaleVector2d(end_.edge_top() - end_.edge_bottom(), 0.5f); + return ComputeLineOffsetFromBottom(end_); } bool TouchSelectionController::GetStartVisible() const {
diff --git a/ui/touch_selection/touch_selection_controller_unittest.cc b/ui/touch_selection/touch_selection_controller_unittest.cc index bdbde62..79c9823 100644 --- a/ui/touch_selection/touch_selection_controller_unittest.cc +++ b/ui/touch_selection/touch_selection_controller_unittest.cc
@@ -730,6 +730,41 @@ EXPECT_FALSE(GetAndResetSelectionMoved()); } +TEST_F(TouchSelectionControllerTest, SelectionDragExtremeLineSize) { + base::TimeTicks event_time = base::TimeTicks::Now(); + controller().OnLongPressEvent(); + + float small_line_height = 1.f; + float large_line_height = 50.f; + gfx::RectF small_line_rect(0, 0, 0, small_line_height); + gfx::RectF large_line_rect(50, 50, 0, large_line_height); + bool visible = true; + ChangeSelection(small_line_rect, visible, large_line_rect, visible); + EXPECT_EQ(SELECTION_SHOWN, GetLastEventType()); + EXPECT_EQ(small_line_rect.bottom_left(), GetLastEventAnchor()); + + // Start dragging the handle on the small line. + MockMotionEvent event(MockMotionEvent::ACTION_DOWN, event_time, + small_line_rect.x(), small_line_rect.y()); + SetDraggingEnabled(true); + EXPECT_TRUE(controller().WillHandleTouchEvent(event)); + EXPECT_EQ(SELECTION_DRAG_STARTED, GetLastEventType()); + // The drag coordinate for large lines should be capped to a reasonable + // offset, allowing seamless transition to neighboring lines with different + // sizes. The drag coordinate for small lines should have an offset + // commensurate with the small line size. + EXPECT_EQ(large_line_rect.bottom_left() - gfx::Vector2dF(0, 5.f), + GetLastSelectionStart()); + EXPECT_EQ(small_line_rect.CenterPoint(), GetLastSelectionEnd()); + + small_line_rect += gfx::Vector2dF(25.f, 0); + event = MockMotionEvent(MockMotionEvent::ACTION_MOVE, event_time, + small_line_rect.x(), small_line_rect.y()); + EXPECT_TRUE(controller().WillHandleTouchEvent(event)); + EXPECT_TRUE(GetAndResetSelectionMoved()); + EXPECT_EQ(small_line_rect.CenterPoint(), GetLastSelectionEnd()); +} + TEST_F(TouchSelectionControllerTest, Animation) { controller().OnTapEvent(); controller().OnSelectionEditable(true);
diff --git a/ui/views/bubble/bubble_frame_view.cc b/ui/views/bubble/bubble_frame_view.cc index e3eb3c8..88628fb 100644 --- a/ui/views/bubble/bubble_frame_view.cc +++ b/ui/views/bubble/bubble_frame_view.cc
@@ -92,7 +92,7 @@ *rb.GetImageNamed(IDR_CLOSE_DIALOG_H).ToImageSkia()); close->SetImage(CustomButton::STATE_PRESSED, *rb.GetImageNamed(IDR_CLOSE_DIALOG_P).ToImageSkia()); - close->SetBorder(scoped_ptr<Border>()); + close->SetBorder(nullptr); close->SetSize(close->GetPreferredSize()); return close; }
diff --git a/ui/views/controls/button/label_button.cc b/ui/views/controls/button/label_button.cc index 52250cf..0387e1d 100644 --- a/ui/views/controls/button/label_button.cc +++ b/ui/views/controls/button/label_button.cc
@@ -191,7 +191,7 @@ style_ = style; // Inset the button focus rect from the actual border; roughly match Windows. if (style == STYLE_BUTTON) { - SetFocusPainter(scoped_ptr<Painter>()); + SetFocusPainter(nullptr); } else { SetFocusPainter(Painter::CreateDashedFocusPainterWithInsets( gfx::Insets(3, 3, 3, 3)));
diff --git a/ui/views/controls/button/menu_button.cc b/ui/views/controls/button/menu_button.cc index aee3930..072e167 100644 --- a/ui/views/controls/button/menu_button.cc +++ b/ui/views/controls/button/menu_button.cc
@@ -72,6 +72,7 @@ IDR_MENU_DROPARROW).ToImageSkia()), destroyed_flag_(NULL), pressed_lock_count_(0), + should_disable_after_press_(false), weak_factory_(this) { SetHorizontalAlignment(gfx::ALIGN_LEFT); } @@ -308,8 +309,22 @@ return event.type() == ui::ET_GESTURE_TAP; } +void MenuButton::StateChanged() { + if (pressed_lock_count_ != 0) { + // The button's state was changed while it was supposed to be locked in a + // pressed state. This shouldn't happen, but conceivably could if a caller + // tries to switch from enabled to disabled or vice versa while the button + // is pressed. + if (state() == STATE_NORMAL) + should_disable_after_press_ = false; + else if (state() == STATE_DISABLED) + should_disable_after_press_ = true; + } +} + void MenuButton::IncrementPressedLocked() { ++pressed_lock_count_; + should_disable_after_press_ = state() == STATE_DISABLED; SetState(STATE_PRESSED); } @@ -317,13 +332,17 @@ --pressed_lock_count_; DCHECK_GE(pressed_lock_count_, 0); - // If this was the last lock, manually reset state to "normal". We set - // "normal" and not "hot" because the likelihood is that the mouse is now - // somewhere else (user clicked elsewhere on screen to close the menu or - // selected an item) and we will inevitably refresh the hot state in the event - // the mouse _is_ over the view. - if (pressed_lock_count_ == 0) - SetState(STATE_NORMAL); + // If this was the last lock, manually reset state to the desired state. + if (pressed_lock_count_ == 0) { + ButtonState desired_state = STATE_NORMAL; + if (should_disable_after_press_) { + desired_state = STATE_DISABLED; + should_disable_after_press_ = false; + } else if (IsMouseHovered()) { + desired_state = STATE_HOVERED; + } + SetState(desired_state); + } } int MenuButton::GetMaximumScreenXCoordinate() {
diff --git a/ui/views/controls/button/menu_button.h b/ui/views/controls/button/menu_button.h index 39a490b..dbff53c1 100644 --- a/ui/views/controls/button/menu_button.h +++ b/ui/views/controls/button/menu_button.h
@@ -87,6 +87,7 @@ // Overridden from CustomButton: bool ShouldEnterPushedState(const ui::Event& event) override; + void StateChanged() override; // Offset of the associated menu position. gfx::Point menu_offset_; @@ -127,6 +128,11 @@ // The current number of "pressed" locks this button has. int pressed_lock_count_; + // True if the button was in a disabled state when a menu was run, and should + // return to it once the press is complete. This can happen if, e.g., we + // programmatically show a menu on a disabled button. + bool should_disable_after_press_; + base::WeakPtrFactory<MenuButton> weak_factory_; DISALLOW_COPY_AND_ASSIGN(MenuButton);
diff --git a/ui/views/controls/button/menu_button_unittest.cc b/ui/views/controls/button/menu_button_unittest.cc index d3fbb1beb..2a17acf 100644 --- a/ui/views/controls/button/menu_button_unittest.cc +++ b/ui/views/controls/button/menu_button_unittest.cc
@@ -348,6 +348,31 @@ // ...And it should respond to mouse movement again. generator.MoveMouseTo(gfx::Point(10, 10)); EXPECT_EQ(Button::STATE_HOVERED, button()->state()); + + // Test that the button returns to the appropriate state after the press; if + // the mouse ends over the button, the button should be hovered. + pressed_lock1.reset(new MenuButton::PressedLock(button())); + EXPECT_EQ(Button::STATE_PRESSED, button()->state()); + pressed_lock1.reset(); + EXPECT_EQ(Button::STATE_HOVERED, button()->state()); + + // If the button is disabled before the pressed lock, it should be disabled + // after the pressed lock. + button()->SetState(Button::STATE_DISABLED); + pressed_lock1.reset(new MenuButton::PressedLock(button())); + EXPECT_EQ(Button::STATE_PRESSED, button()->state()); + pressed_lock1.reset(); + EXPECT_EQ(Button::STATE_DISABLED, button()->state()); + + generator.MoveMouseTo(gfx::Point(300, 10)); + + // Edge case: the button is disabled, a pressed lock is added, and then the + // button is re-enabled. It should be enabled after the lock is removed. + pressed_lock1.reset(new MenuButton::PressedLock(button())); + EXPECT_EQ(Button::STATE_PRESSED, button()->state()); + button()->SetState(Button::STATE_NORMAL); + pressed_lock1.reset(); + EXPECT_EQ(Button::STATE_NORMAL, button()->state()); } // Test that the MenuButton does not become pressed if it can be dragged, until
diff --git a/ui/views/controls/image_view.cc b/ui/views/controls/image_view.cc index e7417ea..01f3011 100644 --- a/ui/views/controls/image_view.cc +++ b/ui/views/controls/image_view.cc
@@ -26,6 +26,9 @@ } // namespace +// static +const char ImageView::kViewClassName[] = "ImageView"; + ImageView::ImageView() : image_size_set_(false), horiz_alignment_(CENTER), @@ -166,6 +169,10 @@ state->name = tooltip_text_; } +const char* ImageView::GetClassName() const { + return kViewClassName; +} + void ImageView::SetHorizontalAlignment(Alignment ha) { if (ha != horiz_alignment_) { horiz_alignment_ = ha;
diff --git a/ui/views/controls/image_view.h b/ui/views/controls/image_view.h index ef207c2..272aec0f 100644 --- a/ui/views/controls/image_view.h +++ b/ui/views/controls/image_view.h
@@ -28,6 +28,9 @@ ///////////////////////////////////////////////////////////////////////////// class VIEWS_EXPORT ImageView : public View { public: + // Internal class name. + static const char kViewClassName[]; + enum Alignment { LEADING = 0, CENTER, @@ -85,6 +88,7 @@ void OnBlur() override; void OnPaint(gfx::Canvas* canvas) override; void GetAccessibleState(ui::AXViewState* state) override; + const char* GetClassName() const override; bool GetTooltipText(const gfx::Point& p, base::string16* tooltip) const override; bool CanProcessEventsWithinSubtree() const override;
diff --git a/ui/views/controls/label.cc b/ui/views/controls/label.cc index 6b8fa58..979a5b0 100644 --- a/ui/views/controls/label.cc +++ b/ui/views/controls/label.cc
@@ -347,7 +347,8 @@ const gfx::Rect& text_bounds, int flags) { SkColor color = enabled() ? actual_enabled_color_ : actual_disabled_color_; - if (elide_behavior_ == gfx::FADE_TAIL) { + if (elide_behavior_ == gfx::FADE_TAIL && + text_bounds.width() < GetTextSize().width()) { canvas->DrawFadedString(text, font_list_, color, text_bounds, flags); } else { canvas->DrawStringRectWithShadows(text, font_list_, color, text_bounds,
diff --git a/ui/views/controls/message_box_view.cc b/ui/views/controls/message_box_view.cc index 2c0f102..1993f6d 100644 --- a/ui/views/controls/message_box_view.cc +++ b/ui/views/controls/message_box_view.cc
@@ -66,6 +66,9 @@ /////////////////////////////////////////////////////////////////////////////// // MessageBoxView, public: +// static +const char MessageBoxView::kViewClassName[] = "MessageBoxView"; + MessageBoxView::InitParams::InitParams(const base::string16& message) : options(NO_OPTIONS), message(message), @@ -158,6 +161,10 @@ return true; } +const char* MessageBoxView::GetClassName() const { + return kViewClassName; +} + /////////////////////////////////////////////////////////////////////////////// // MessageBoxView, private:
diff --git a/ui/views/controls/message_box_view.h b/ui/views/controls/message_box_view.h index 120999a3..2bb4331 100644 --- a/ui/views/controls/message_box_view.h +++ b/ui/views/controls/message_box_view.h
@@ -23,6 +23,9 @@ // and Cancel buttons. class VIEWS_EXPORT MessageBoxView : public View { public: + // Internal class name. + static const char kViewClassName[]; + enum Options { NO_OPTIONS = 0, // For a message from a web page (not from Chrome's UI), such as script @@ -82,6 +85,7 @@ const ViewHierarchyChangedDetails& details) override; // Handles Ctrl-C and writes the message in the system clipboard. bool AcceleratorPressed(const ui::Accelerator& accelerator) override; + const char* GetClassName() const override; private: // Sets up the layout manager and initializes the message labels and prompt
diff --git a/ui/views/controls/slider.cc b/ui/views/controls/slider.cc index f1d2bc34..b5c71c2 100644 --- a/ui/views/controls/slider.cc +++ b/ui/views/controls/slider.cc
@@ -51,6 +51,9 @@ namespace views { +// static +const char Slider::kViewClassName[] = "Slider"; + Slider::Slider(SliderListener* listener, Orientation orientation) : listener_(listener), orientation_(orientation), @@ -186,6 +189,10 @@ } } +const char* Slider::GetClassName() const { + return kViewClassName; +} + gfx::Size Slider::GetPreferredSize() const { const int kSizeMajor = 200; const int kSizeMinor = 40;
diff --git a/ui/views/controls/slider.h b/ui/views/controls/slider.h index 22b1f12..afe7516 100644 --- a/ui/views/controls/slider.h +++ b/ui/views/controls/slider.h
@@ -47,6 +47,9 @@ class VIEWS_EXPORT Slider : public View, public gfx::AnimationDelegate { public: + // Internal class name. + static const char kViewClassName[]; + enum Orientation { HORIZONTAL, VERTICAL @@ -94,6 +97,7 @@ void OnSliderDragEnded(); // views::View overrides: + const char* GetClassName() const override; gfx::Size GetPreferredSize() const override; void OnPaint(gfx::Canvas* canvas) override; bool OnMousePressed(const ui::MouseEvent& event) override;
diff --git a/ui/views/controls/styled_label.cc b/ui/views/controls/styled_label.cc index 44e42ed..172a479 100644 --- a/ui/views/controls/styled_label.cc +++ b/ui/views/controls/styled_label.cc
@@ -92,6 +92,9 @@ // StyledLabel ---------------------------------------------------------------- +// static +const char StyledLabel::kViewClassName[] = "StyledLabel"; + StyledLabel::StyledLabel(const base::string16& text, StyledLabelListener* listener) : specified_line_height_(0), @@ -156,6 +159,10 @@ } } +const char* StyledLabel::GetClassName() const { + return kViewClassName; +} + gfx::Insets StyledLabel::GetInsets() const { gfx::Insets insets = View::GetInsets();
diff --git a/ui/views/controls/styled_label.h b/ui/views/controls/styled_label.h index adbd7a9..40cdafb7 100644 --- a/ui/views/controls/styled_label.h +++ b/ui/views/controls/styled_label.h
@@ -29,6 +29,9 @@ // In this case, leading whitespace is ignored. class VIEWS_EXPORT StyledLabel : public View, public LinkListener { public: + // Internal class name. + static const char kViewClassName[]; + // Parameters that define label style for a styled label's text range. struct VIEWS_EXPORT RangeStyleInfo { RangeStyleInfo(); @@ -90,7 +93,8 @@ auto_color_readability_enabled_ = auto_color_readability; } - // View implementation: + // views::View: + const char* GetClassName() const override; gfx::Insets GetInsets() const override; int GetHeightForWidth(int w) const override; void Layout() override;
diff --git a/ui/views/controls/table/table_header.cc b/ui/views/controls/table/table_header.cc index a9d730f..5473490 100644 --- a/ui/views/controls/table/table_header.cc +++ b/ui/views/controls/table/table_header.cc
@@ -40,6 +40,8 @@ } // namespace // static +const char TableHeader::kViewClassName[] = "TableHeader"; +// static const int TableHeader::kHorizontalPadding = 7; // static const int TableHeader::kSortIndicatorWidth = kSortIndicatorSize + @@ -159,6 +161,10 @@ } } +const char* TableHeader::GetClassName() const { + return kViewClassName; +} + gfx::Size TableHeader::GetPreferredSize() const { return gfx::Size(1, kVerticalPadding * 2 + font_list_.GetHeight()); }
diff --git a/ui/views/controls/table/table_header.h b/ui/views/controls/table/table_header.h index b048a29a..e88bad6 100644 --- a/ui/views/controls/table/table_header.h +++ b/ui/views/controls/table/table_header.h
@@ -16,6 +16,9 @@ // Views used to render the header for the table. class VIEWS_EXPORT TableHeader : public views::View { public: + // Internal class name. + static const char kViewClassName[]; + // Amount the text is padded on the left/right side. static const int kHorizontalPadding; @@ -30,6 +33,7 @@ // views::View overrides. void Layout() override; void OnPaint(gfx::Canvas* canvas) override; + const char* GetClassName() const override; gfx::Size GetPreferredSize() const override; gfx::NativeCursor GetCursor(const ui::MouseEvent& event) override; bool OnMousePressed(const ui::MouseEvent& event) override;
diff --git a/ui/views/controls/table/table_view.cc b/ui/views/controls/table/table_view.cc index b94d487d..0b2d735 100644 --- a/ui/views/controls/table/table_view.cc +++ b/ui/views/controls/table/table_view.cc
@@ -118,6 +118,9 @@ TableView::PaintRegion::~PaintRegion() {} +// static +const char TableView::kViewClassName[] = "TableView"; + TableView::TableView(ui::TableModel* model, const std::vector<ui::TableColumn>& columns, TableTypes table_type, @@ -321,6 +324,10 @@ SetBounds(x(), y(), width, height); } +const char* TableView::GetClassName() const { + return kViewClassName; +} + gfx::Size TableView::GetPreferredSize() const { int width = 50; if (header_ && !visible_columns_.empty())
diff --git a/ui/views/controls/table/table_view.h b/ui/views/controls/table/table_view.h index 66302e5..bfe0e525 100644 --- a/ui/views/controls/table/table_view.h +++ b/ui/views/controls/table/table_view.h
@@ -52,6 +52,9 @@ : public views::View, public ui::TableModelObserver { public: + // Internal class name. + static const char kViewClassName[]; + // Used to track a visible column. Useful only for the header. struct VIEWS_EXPORT VisibleColumn { VisibleColumn(); @@ -166,6 +169,7 @@ // View overrides: void Layout() override; + const char* GetClassName() const override; gfx::Size GetPreferredSize() const override; bool OnKeyPressed(const ui::KeyEvent& event) override; bool OnMousePressed(const ui::MouseEvent& event) override;
diff --git a/ui/views/widget/desktop_aura/desktop_cursor_loader_updater_aurawin.cc b/ui/views/widget/desktop_aura/desktop_cursor_loader_updater_aurawin.cc index cb94880..eadc1ca 100644 --- a/ui/views/widget/desktop_aura/desktop_cursor_loader_updater_aurawin.cc +++ b/ui/views/widget/desktop_aura/desktop_cursor_loader_updater_aurawin.cc
@@ -8,7 +8,7 @@ // static scoped_ptr<DesktopCursorLoaderUpdater> DesktopCursorLoaderUpdater::Create() { - return scoped_ptr<DesktopCursorLoaderUpdater>().Pass(); + return nullptr; } } // namespace views
diff --git a/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc b/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc index 8a56b8de..70db0361 100644 --- a/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc +++ b/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc
@@ -9,6 +9,7 @@ #include "base/event_types.h" #include "base/lazy_instance.h" #include "base/message_loop/message_loop.h" +#include "base/metrics/histogram_macros.h" #include "third_party/skia/include/core/SkBitmap.h" #include "ui/aura/client/capture_client.h" #include "ui/aura/window.h" @@ -610,6 +611,10 @@ event.set_flags(XGetModifiers()); } + if (!IsDragDropInProgress()) { + UMA_HISTOGRAM_COUNTS("Event.DragDrop.ExternalOriginDrop", 1); + } + drag_operation = delegate->OnPerformDrop(event); } @@ -646,6 +651,9 @@ const gfx::Point& root_location, int operation, ui::DragDropTypes::DragEventSource source) { + UMA_HISTOGRAM_ENUMERATION("Event.DragDrop.Start", source, + ui::DragDropTypes::DRAG_EVENT_SOURCE_COUNT); + source_current_window_ = None; DCHECK(!g_current_drag_drop_client); g_current_drag_drop_client = this; @@ -699,6 +707,13 @@ cursor_manager_->GetInitializedCursor(ui::kCursorGrabbing)); if (alive) { + if (negotiated_operation_ == ui::DragDropTypes::DRAG_NONE) { + UMA_HISTOGRAM_ENUMERATION("Event.DragDrop.Cancel", source, + ui::DragDropTypes::DRAG_EVENT_SOURCE_COUNT); + } else { + UMA_HISTOGRAM_ENUMERATION("Event.DragDrop.Drop", source, + ui::DragDropTypes::DRAG_EVENT_SOURCE_COUNT); + } drag_widget_.reset(); source_provider_ = NULL; @@ -709,6 +724,8 @@ return negotiated_operation_; } + UMA_HISTOGRAM_ENUMERATION("Event.DragDrop.Cancel", source, + ui::DragDropTypes::DRAG_EVENT_SOURCE_COUNT); return ui::DragDropTypes::DRAG_NONE; }
diff --git a/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.cc b/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.cc index 49c20e90..25699e50 100644 --- a/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.cc +++ b/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.cc
@@ -4,6 +4,7 @@ #include "ui/views/widget/desktop_aura/desktop_drag_drop_client_win.h" +#include "base/metrics/histogram_macros.h" #include "base/tracked_objects.h" #include "ui/base/dragdrop/drag_drop_types.h" #include "ui/base/dragdrop/drag_source_win.h" @@ -45,6 +46,9 @@ DWORD effect; + UMA_HISTOGRAM_ENUMERATION("Event.DragDrop.Start", source, + ui::DragDropTypes::DRAG_EVENT_SOURCE_COUNT); + // Use task stopwatch to exclude the drag-drop time current task, if any. tracked_objects::TaskStopwatch stopwatch; stopwatch.Start(); @@ -59,7 +63,17 @@ if (result != DRAGDROP_S_DROP) effect = DROPEFFECT_NONE; - return ui::DragDropTypes::DropEffectToDragOperation(effect); + int drag_operation = ui::DragDropTypes::DropEffectToDragOperation(effect); + + if (drag_operation == ui::DragDropTypes::DRAG_NONE) { + UMA_HISTOGRAM_ENUMERATION("Event.DragDrop.Cancel", source, + ui::DragDropTypes::DRAG_EVENT_SOURCE_COUNT); + } else { + UMA_HISTOGRAM_ENUMERATION("Event.DragDrop.Drop", source, + ui::DragDropTypes::DRAG_EVENT_SOURCE_COUNT); + } + + return drag_operation; } void DesktopDragDropClientWin::DragUpdate(aura::Window* target,
diff --git a/ui/views/widget/desktop_aura/desktop_drop_target_win.cc b/ui/views/widget/desktop_aura/desktop_drop_target_win.cc index 1369b62e..f10fc1f 100644 --- a/ui/views/widget/desktop_aura/desktop_drop_target_win.cc +++ b/ui/views/widget/desktop_aura/desktop_drop_target_win.cc
@@ -4,6 +4,7 @@ #include "ui/views/widget/desktop_aura/desktop_drop_target_win.h" +#include "base/metrics/histogram.h" #include "base/win/win_util.h" #include "ui/aura/window.h" #include "ui/aura/window_tree_host.h" @@ -14,6 +15,7 @@ #include "ui/wm/public/drag_drop_client.h" #include "ui/wm/public/drag_drop_delegate.h" +using aura::client::DragDropClient; using aura::client::DragDropDelegate; using ui::OSExchangeData; using ui::OSExchangeDataProviderWin; @@ -72,8 +74,14 @@ scoped_ptr<ui::DropTargetEvent> event; DragDropDelegate* delegate; Translate(data_object, key_state, position, effect, &data, &event, &delegate); - if (delegate) + if (delegate) { drag_operation = delegate->OnPerformDrop(*event); + DragDropClient* client = aura::client::GetDragDropClient(root_window_); + if (client && !client->IsDragDropInProgress() && + drag_operation != ui::DragDropTypes::DRAG_NONE) { + UMA_HISTOGRAM_COUNTS("Event.DragDrop.ExternalOriginDrop", 1); + } + } if (target_window_) { target_window_->RemoveObserver(this); target_window_ = NULL;
diff --git a/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc b/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc index 88c6090..05a968c 100644 --- a/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc +++ b/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
@@ -145,8 +145,11 @@ void OnWindowBoundsChanged(aura::Window* window, const gfx::Rect& old_bounds, const gfx::Rect& new_bounds) override { + // The position of the window may have changed. Hence we use SetBounds in + // place of SetSize. We need to pass the bounds in screen coordinates to + // the Widget::SetBounds function. if (top_level_widget_ && window == child_window_) - top_level_widget_->SetSize(new_bounds.size()); + top_level_widget_->SetBounds(window->GetBoundsInScreen()); } private: @@ -870,7 +873,10 @@ } bool DesktopNativeWidgetAura::IsMouseEventsEnabled() const { - if (!content_window_) + // We explicitly check |host_| here because it can be null during the process + // of widget shutdown (even if |content_window_| is not), and must be valid to + // determine if mouse events are enabled. + if (!content_window_ || !host_) return false; aura::client::CursorClient* cursor_client = aura::client::GetCursorClient(host_->window());
diff --git a/ui/views/widget/desktop_aura/desktop_native_widget_aura_unittest.cc b/ui/views/widget/desktop_aura/desktop_native_widget_aura_unittest.cc index 975a2179..60eef52 100644 --- a/ui/views/widget/desktop_aura/desktop_native_widget_aura_unittest.cc +++ b/ui/views/widget/desktop_aura/desktop_native_widget_aura_unittest.cc
@@ -12,6 +12,7 @@ #include "ui/aura/window.h" #include "ui/aura/window_tree_host.h" #include "ui/events/test/event_generator.h" +#include "ui/gfx/screen.h" #include "ui/views/test/views_test_base.h" #include "ui/views/test/widget_test.h" #include "ui/views/widget/widget.h" @@ -249,7 +250,8 @@ : top_level_widget_(NULL), owned_window_(NULL), owner_destroyed_(false), - owned_window_destroyed_(false) {} + owned_window_destroyed_(false), + use_async_mode_(true) {} ~DesktopAuraTopLevelWindowTest() override { EXPECT_TRUE(owner_destroyed_); @@ -302,6 +304,13 @@ void DestroyOwnedWindow() { ASSERT_TRUE(owned_window_ != NULL); + // If async mode is off then clean up state here. + if (!use_async_mode_) { + owned_window_->RemoveObserver(this); + owned_window_->parent()->RemoveObserver(this); + owner_destroyed_ = true; + owned_window_destroyed_ = true; + } delete owned_window_; } @@ -329,6 +338,10 @@ return top_level_widget_; } + void set_use_async_mode(bool async_mode) { + use_async_mode_ = async_mode; + } + private: views::Widget widget_; views::Widget* top_level_widget_; @@ -336,6 +349,9 @@ bool owner_destroyed_; bool owned_window_destroyed_; aura::test::TestWindowDelegate child_window_delegate_; + // This flag controls whether we need to wait for the destruction to complete + // before finishing the test. Defaults to true. + bool use_async_mode_; DISALLOW_COPY_AND_ASSIGN(DesktopAuraTopLevelWindowTest); }; @@ -381,6 +397,9 @@ TEST_F(DesktopAuraWidgetTest, TopLevelOwnedPopupResizeTest) { ViewsDelegate::views_delegate = NULL; DesktopAuraTopLevelWindowTest popup_window; + + popup_window.set_use_async_mode(false); + ASSERT_NO_FATAL_FAILURE(popup_window.CreateTopLevelWindow( gfx::Rect(0, 0, 200, 200), false)); @@ -389,9 +408,31 @@ EXPECT_EQ(popup_window.top_level_widget()->GetNativeView()->bounds().size(), new_size.size()); - RunPendingMessages(); + ASSERT_NO_FATAL_FAILURE(popup_window.DestroyOwnedWindow()); - RunPendingMessages(); +} + +// This test validates that when a top level owned popup Aura window is +// repositioned, the widget is repositioned as well. +TEST_F(DesktopAuraWidgetTest, TopLevelOwnedPopupRepositionTest) { + ViewsDelegate::views_delegate = NULL; + DesktopAuraTopLevelWindowTest popup_window; + + popup_window.set_use_async_mode(false); + + ASSERT_NO_FATAL_FAILURE(popup_window.CreateTopLevelWindow( + gfx::Rect(0, 0, 200, 200), false)); + + gfx::Rect new_pos(10, 10, 400, 400); + popup_window.owned_window()->SetBoundsInScreen( + new_pos, + gfx::Screen::GetScreenFor( + popup_window.owned_window())->GetDisplayNearestPoint(gfx::Point())); + + EXPECT_EQ(new_pos, + popup_window.top_level_widget()->GetWindowBoundsInScreen()); + + ASSERT_NO_FATAL_FAILURE(popup_window.DestroyOwnedWindow()); } } // namespace test
diff --git a/ui/views/win/hwnd_message_handler.cc b/ui/views/win/hwnd_message_handler.cc index 6345b794..d23127df 100644 --- a/ui/views/win/hwnd_message_handler.cc +++ b/ui/views/win/hwnd_message_handler.cc
@@ -2470,14 +2470,9 @@ touch_event_type = ui::ET_TOUCH_MOVED; } if (touch_event_type != ui::ET_UNKNOWN) { - base::TimeTicks now; // input[i].dwTime doesn't necessarily relate to the system time at all, - // so use base::TimeTicks::HighResNow() if possible, or - // base::TimeTicks::Now() otherwise. - if (base::TimeTicks::IsHighResNowFastAndReliable()) - now = base::TimeTicks::HighResNow(); - else - now = base::TimeTicks::Now(); + // so use base::TimeTicks::Now() + const base::TimeTicks now = base::TimeTicks::Now(); ui::TouchEvent event(touch_event_type, gfx::Point(point.x, point.y), id_generator_.GetGeneratedID(input[i].dwID),
diff --git a/ui/webui/resources/css/text_defaults.css b/ui/webui/resources/css/text_defaults.css index 3e9007a..682a8585 100644 --- a/ui/webui/resources/css/text_defaults.css +++ b/ui/webui/resources/css/text_defaults.css
@@ -6,11 +6,14 @@ * some per-platform/locale styles that dramatically alter the page. This is * done to reduce flicker, as JS may not run before the page is rendered. * - * Include this stylesheet via its chrome://resources/ URL, i.e.: + * There are two ways to include this stylesheet: + * 1. via its chrome://resources/ URL in HTML, i.e.: * - * <link rel="stylesheet" href="chrome://resources/css/font_defaults.css"> + * <link rel="stylesheet" href="chrome://resources/css/text_defaults.css"> * - * otherwise its $placeholders wont be expanded. */ + * 2. via the webui::AppendWebUICSSTextDefaults() method to directly append it + * to an HTML string. + * Otherwise its $placeholders won't be expanded. */ html { direction: $1;
diff --git a/ui/wm/core/nested_accelerator_dispatcher_linux.cc b/ui/wm/core/nested_accelerator_dispatcher_linux.cc index 3016fc0..a5ce30a3 100644 --- a/ui/wm/core/nested_accelerator_dispatcher_linux.cc +++ b/ui/wm/core/nested_accelerator_dispatcher_linux.cc
@@ -38,8 +38,7 @@ scoped_ptr<ui::ScopedEventDispatcher> OverrideDispatcher( ui::PlatformEventDispatcher* dispatcher) { ui::PlatformEventSource* source = ui::PlatformEventSource::GetInstance(); - return source ? source->OverrideDispatcher(dispatcher) - : scoped_ptr<ui::ScopedEventDispatcher>(); + return source ? source->OverrideDispatcher(dispatcher) : nullptr; } } // namespace
diff --git a/url/gurl_unittest.cc b/url/gurl_unittest.cc index a6991891..bea1a0c 100644 --- a/url/gurl_unittest.cc +++ b/url/gurl_unittest.cc
@@ -281,6 +281,9 @@ const char* expected; } resolve_cases[] = { {"http://www.google.com/", "foo.html", true, "http://www.google.com/foo.html"}, + {"http://www.google.com/foo/", "bar", true, "http://www.google.com/foo/bar"}, + {"http://www.google.com/foo/", "/bar", true, "http://www.google.com/bar"}, + {"http://www.google.com/foo", "bar", true, "http://www.google.com/bar"}, {"http://www.google.com/", "http://images.google.com/foo.html", true, "http://images.google.com/foo.html"}, {"http://www.google.com/blah/bloo?c#d", "../../../hello/./world.html?a#b", true, "http://www.google.com/hello/world.html?a#b"}, {"http://www.google.com/foo#bar", "#com", true, "http://www.google.com/foo#com"},
diff --git a/win8/viewer/metro_viewer_process_host.cc b/win8/viewer/metro_viewer_process_host.cc index 2e04ef8..61a776c 100644 --- a/win8/viewer/metro_viewer_process_host.cc +++ b/win8/viewer/metro_viewer_process_host.cc
@@ -12,7 +12,6 @@ #include "base/memory/ref_counted.h" #include "base/path_service.h" #include "base/process/process.h" -#include "base/process/process_handle.h" #include "base/strings/string16.h" #include "base/synchronization/waitable_event.h" #include "base/time/time.h" @@ -68,14 +67,13 @@ if (message_filter_.get()) { // Wait for the viewer process to go away. if (viewer_process_id != base::kNullProcessId) { - base::ProcessHandle viewer_process = NULL; - base::OpenProcessHandleWithAccess( - viewer_process_id, - PROCESS_QUERY_INFORMATION | SYNCHRONIZE, - &viewer_process); - if (viewer_process) { - ::WaitForSingleObject(viewer_process, INFINITE); - ::CloseHandle(viewer_process); + base::Process viewer_process = + base::Process::OpenWithAccess( + viewer_process_id, + PROCESS_QUERY_INFORMATION | SYNCHRONIZE); + if (viewer_process.IsValid()) { + int exit_code; + viewer_process.WaitForExit(&exit_code); } } channel_->RemoveFilter(message_filter_.get());